iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > JAVA >Java 基础-Java8
  • 132
分享到

Java 基础-Java8

javajvm开发语言JDK8JAVA8 2023-10-24 21:10:55 132人浏览 独家记忆
摘要

Java 8介绍 Java 8的主要新语法特性如下: Lambda表达式 Lambda表达式使Java程序员能够编写更加简洁、易读和易维护的代码。它是一种匿名函数,可以将其作为参数传递给其他方法或


Java 8介绍

Java 8的主要新语法特性如下:

  1. Lambda表达式
    Lambda表达式使Java程序员能够编写更加简洁、易读和易维护的代码。它是一种匿名函数,可以将其作为参数传递给其他方法或函数。

  2. 方法引用
    方法引用是指通过名称来引用现有的方法,从而让代码变得更简洁、易读和易于维护。Java 8中提供了四种不同的方法引用方式:静态方法引用、实例方法引用、构造器引用和超类方法引用。

  3. 接口默认方法
    Java 8允许在接口中定义具体实现的默认方法,这样实现类就可以继承该方法的实现,避免了因为新增方法而导致向所有实现类迁移代码的麻烦。

  4. 函数式接口
    函数式接口仅包含一个抽象方法的接口,它是Java 8中Lambda表达式的基础。Java 8中提供了许多常用的函数式接口,例如:Predicate、Function、Consumer等。

  5. Stream api
    Stream API是Java 8中一个强大的工具,它允许程序员轻松处理集合数据。使用流API可以实现筛选、排序、映射、归约等操作,让代码更加简洁、易读和易于维护。

  6. 时间API
    Java 8中引入了新的时间API,它提供了一种更好的方式来处理日期和时间。这个API包含多个类,可以用来处理日历、时间、时区和持续时间等问题。

  7. Optional 类型
    Optional类型是一个容器对象,可以包含null或非null值。它为程序员提供一种优雅的方式来处理null检查,从而避免NullPointerException异常。

这些新语法都带来了很大的变化,使得Java编程更加简洁、高效、可读性强和易于维护。

Lambda 表达式

Lambda是一个 匿名函数,我们可以把Lambda表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

基础语法

Java8引入了一个新的操作符: ->,该操作符称为箭头操作符或Lambda操作符,箭头操作符将Lambda表达式拆分为2部分:

  1. 左侧:Lambda表达式的 参数列表
  2. 右侧:Lambda表达式中 所执行的功能,即Lambda体

语法格式1:无参数,无返回值

public class test {    public static void main(String[] args) {        Runnable r = new Runnable() {            @Override            public void run() {                System.out.println("Hello World!");            }        };        r.run();        System.out.println("--------------------------------------");        Runnable r1 = () -> System.out.println("Hello Lambda");        r1.run();    }}

语法格式2:有一个参数,并且无返回值,小括号可省略不写,:

public class test {    public static void main(String[] args) {        Consumer<String> con = x -> System.out.println(x);        con.accept("SNOW");    }}

语法格式3:有2个以上的参数,有返回值,并且Lambda体中有多条语句 ,有返回值

public class test {    public static void main(String[] args) {        Comparator<Integer> com = (x,y) -> {            System.out.println("函数式接口");            return Integer.compare(x,y);        };    }}

语法格式4:若Lambda体中只有一条语句,return和大括号都可省略不写

public class test {    public static void main(String[] args) {        Comparator<Integer> com = (x,y) -> Integer.compare(x,y);    }}

语法格式5:Lambda表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出数据类型,即“类型推断”

Lambda表达式需要 函数式接口 的支持!(函数式接口:接口中只有一个抽象方法的接口,称为函数式接口,可以使用 @FunctionalInterface 修饰。)

案例

@Data@AllArgsConstructor@NoArgsConstructorpublic class Employee {    private String name;    private int age;    private Double salary;}
public class test {    public static void main(String[] args) {        List<Employee> list = Arrays.asList(                new Employee("1号", 25, 5000.0),                new Employee("2号", 35, 3000.0),                new Employee("3号", 35, 2000.0),                new Employee("4号", 35, 8000.0),                new Employee("5号", 65, 1000.0)        );        Collections.sort(list,(e1,e2)->{            if (e1.getAge() == e2.getAge()){                return e1.getName().compareTo(e2.getName());            }else {                // 倒序                return -Integer.compare(e1.getAge(),e2.getAge());            }        });        Iterator<Employee> iterator = list.iterator();        while (iterator.hasNext()){            System.out.println(iterator.next());        }    }}

函数式接口

内置的四大核心函数式接口

  1. Consumer:消费型接口 void accept(T t);
  2. Supplier:供给型接口 T get();
  3. Function(T,R):函数型接口 R apply(T t);
  4. Predicate:断言型接口 boolean test(T t);

案例

  1. Consumer:消费型接口
@Testpublic void test(){    this.happy(1000,m -> {        System.out.println("我消费了"+ m);    });}public void happy(double money, Consumer<Double> con){    con.accept(money);}
  1. Supplier:供给型接口
@Testpublic void test(){    List<Integer> numList = this.getNumList(5, () -> (int) (Math.random() * 100));    for (Integer integer : numList) {        System.out.println(integer);    }}//产生指定数量的整数public List<Integer> getNumList(int num, Supplier<Integer> sup){    List<Integer> list = new ArrayList<>();    for (int i = 0; i < num; i++) {        list.add(sup.get());    }    return list;}
  1. Function(T,R):函数型接口
@Testpublic void test(){    System.out.println(this.handler("str", str -> (str + "123")));}//处理字符串public String handler(String str, Function<String,String> fun){    return fun.apply(str);}
  1. Predicate:断言型接口
@Testpublic void test(){    List<String> stringList = Arrays.asList("qwe", "123", "hello", "ranhaifeng", "asdasdsaewqewqe");    List<String> list = filterStr(stringList, s -> (s.length() > 3));    for (String s : list) {        System.out.println(s);    }}//将满足条件的字符串放入集合public List<String> filterStr(List<String> list, Predicate<String> pre){    List<String> stringList = new ArrayList<>();    for (String s : list) {        if (pre.test(s)){            stringList.add(s);        }    }    return stringList;}

方法引用与构造器引用

方法引用

方法引用:若 Lambda 体中的内容有方法已经实现了,我们可以使用“方法引用”,可以理解为方法引用是Lambda表达式的另外一种表现形式。
主要有三种语法格式:

  • 对象::实例方法名
  • 类::静态方法名
  • 类::实例方法名
//对象::实例方法@Testpublic void test(){    Consumer<String> con = x -> {        System.out.println(x);    };     PrintStream out = System.out;    Consumer<String> con1 = out::println;    Consumer<String> con2 = System.out::println;    con2.accept("qwe");} //类::静态方法名@Testpublic void test(){    int x;int y;    Comparator<Integer> com = (x,y)-> Integer.compare(x,y);    Comparator<Integer> com1 = Integer::compare;}// 类::实例方法名@Testpublic void test(){    BiPredicate<String,String> bp = (x,y) -> x.equals(y);    BiPredicate<String,String> bp2 = String::equals;}

注意:

  • Lambda体中调用方法的参数列表与返回值类型,要与函数式接口中抽象方法的函数列表和返回值类型保持一致!
  • 若Lambda参数列表中的第一参数是实例方法的调用者,第二个参数是实例方法的参数时,可以使用ClassName::method

构造器引用

@Testpublic void test(){    Supplier<Object> sup = () -> new Object();    Supplier<Object> sup2 = Object::new;    //如果有多个构造器,如何判断是调用的实体类的哪个构造器呢?看下面的注意,即Function(T,R)内部的函数 R apply(T t) 是1个参数,那么就会调用是1个参数的构造器。    Function<Integer,Employee> fun2 =Employee::new;}

注意:需要调用的构造器的参数列表要与函数式接口中抽象方法的参数列表保持一致!

并行流与串行流

  1. 并行流就是把一个内容分成多个数据块,并用不同的线程分别处理每个数据块的流。Java 8 中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API可以声明性地通过parallel() 与sequential()在并行流与顺序流之间进行切换。
  2. fork/join框架:就是在必要的情况下,将一个大任务,进行拆分(fork)成若干个小任务(拆到不可再拆时),再将一个个的小任务运算的结果进行 join 汇总。
  3. Fork/Join框架与传统线程池的区别:采用工作窃取模式(work-stealing)

当执行新的任务时它可以将其拆分分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放在自己的队列中。
相对于一般的线程池实现, fork/join框架的优势体现仕对其中包含的任务的处理方式上。在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态.而在fork/join框架实现中,如果某个子问题由于等待另外一个子问题的完成而无法继续运行。那么处理该子问题的线程会主动寻找其他尚未运行的子问题来执行,这种方式减少了线程的等待时间,提高了性能。

public class ForkJoinCalculate extends RecursiveTask<Long> {    private static final long serialVersionUID = 12313435L;    private long start;    private long end;    private static final long THRESHOLD = 10000;    public ForkJoinCalculate(long start,long end){        this.start = start;        this.end = end;    }    @Override    protected Long compute() {        long length = end - start;        if (length <= THRESHOLD){            long sum = 0;            for (long i = start; i <= end ; i++) {                sum+= i;            }            return sum;        }else {            long middle = (start + end )/2;            ForkJoinCalculate left = new ForkJoinCalculate(start,middle);            left.fork(); //拆分子任务,同时压入线程队列            ForkJoinCalculate right = new ForkJoinCalculate(middle + 1,end);            right.fork();            return left.join() + right.join();        }    }}
@Testpublic void qwe(){    Instant start = Instant.now();    ForkJoinPool forkJoinPool = new ForkJoinPool();    ForkJoinCalculate forkJoinCalculate = new ForkJoinCalculate(0, 10000000000L);    Long sum = forkJoinPool.invoke(forkJoinCalculate);    System.out.println(sum);    Instant end = Instant.now();    System.out.println("消耗时间:" + Duration.between(start,end).toMillis());   //5701}//普通for循环计算@Testpublic void test2(){    Instant start = Instant.now();    long sum = 0L;    for (int i = 0; i < 10000000000L; i++) {        sum += i;    }    System.out.println(sum);    Instant end = Instant.now();    System.out.println("消耗时间:" + Duration.between(start,end).toMillis());   //没跑出来}//java8并行流@Testpublic void test3(){    Instant start = Instant.now();    LongStream.rangeClosed(0,10000000000L)            .parallel()            .reduce(0,Long::sum);    Instant end = Instant.now();    System.out.println("消耗时间:" + Duration.between(start,end).toMillis());   //2145}

Optional 容器

image.png

 @Test    public void test(){        // Option.of(T t):创建一个Optional实例        Optional<Person> op = Optional.of(new Person());        Person person = op.get();        System.out.println(person); // Person(name=null, age=null, sale=null, status=null)    }    @Test    public void test2(){        // Option.empty():创建一个空Optional实例        Optional<Object> op = Optional.empty();        System.out.println(op.get());   // java.util.NoSuchElementException: No value present    }    @Test    public void test3(){        // Option.ofNullable(T t):若t不为null,创建Optional实例,否则创建空实例        Optional<Object> op = Optional.ofNullable(new Person());        System.out.println(op.get());   // Person(name=null, age=null, sale=null, status=null)    }    @Test    public void test4(){        Optional<Person> op = Optional.ofNullable(new Person());        // Option.isPresent():判断是否包含值        if (op.isPresent()){            System.out.println(op.get());   // Person(name=null, age=null, sale=null, status=null)        }    }    @Test    public void test5(){        Optional<Person> op = Optional.ofNullable(null);        // Option.orElse(T t):如果调用对象包含值,返回该值,否则返回t        Person emp = op.orElse(new Person("qwe", 18, 2000.2, Person.Status.BUSY));        System.out.println(emp);    // Person(name=qwe, age=18, sale=2000.2, status=BUSY)    }    @Test    public void test6(){        Optional<Person> op = Optional.ofNullable(null);        //如果调用对象包含值,返回该值,否则返回s获取的值        Person person = op.orElseGet(() -> new Person());        System.out.println(person);     // Person(name=null, age=null, sale=null, status=null)    }    @Test    public void test7(){        Optional<Person> op = Optional.ofNullable(new Person("qwe", 18, 200.0, Person.Status.BUSY));        // map(Function f):如果有值对其处理,并返回处理后的Optional,否则返回Optional.empty()        Optional<String> str = op.map(e -> e.getName());        System.out.println(str.get());  // qwe        // faltMap(Function mapper):map类似,要求返回值必须是Optional,方法中必须用Optional包装        Optional<String> str2 = op.flatMap(e -> Optional.of(e.getName()));        System.out.println(str2.get()); }

接口中的默认方法与静态方法

接口默认方法的”类优先”原则:
若一个接口中定义了一个默认方法,而另外一个父类或接口中又定义了一个同名的方法时选择父类中的方法。如果一个父类提供了具体的实现,那么接口中具有相同名称和参数的默认方法会被忽略。
接口冲突。
如果一个父接口提供一个默认方法,而另一个接口也提供了一个具有相同名称和参数列表的方法(不管方法是否是默认方法),那么必须覆盖该方法来解决冲突。

接口中的默认方法:

public interface MyFun {    public static void show(){        System.out.println("接口中的静态方法");    }}

新时间日期 API

LocalDate、LocalTime、LocalDateTime

LocalDateTime

@Testpublic void test() {        LocalDateTime now = LocalDateTime.now();    System.out.println(now);    // 2021-12-24T14:51:37.161    //LocalDataTime实例创建    LocalDateTime ldt = LocalDateTime.of(2021, 12, 23, 13, 23, 32);    System.out.println(ldt);    // 2021-12-23T13:23:32    //年份加    LocalDateTime ldt2 = ldt.plusYears(2);    System.out.println(ldt2);   // 2023-12-23T13:23:32    //月份减    LocalDateTime ldt3 = ldt.minusMonths(2);    System.out.println(ldt3);   // 2021-10-23T13:23:32    //获取时间的各个值    System.out.println(ldt.getYear());          //  2021    System.out.println(ldt.getMonthValue());    //  12    System.out.println(ldt.getDayOfMonth());    //  23    System.out.println(ldt.getHour());          //  13    System.out.println(ldt.getMinute());        //  23    System.out.println(ldt.getSecond());        //  32}

Instant:时间戳(以Unix元年:1970年1月1日 00:00:00 到某个时间之间的毫秒值)

public class test {    @Test    public void test() {        Instant ins = Instant.now();    //  默认获取UTC时区        System.out.println(ins);        // 带偏移量,这里表示东八区        OffsetDateTime odt = ins.atOffset(ZoneOffset.ofHours(8));           System.out.println(odt);            System.out.println(ins.toEpochMilli()); // 1640329758791        Instant instant = Instant.ofEpochSecond(60);    // 1970-01-01T00:01:00Z        System.out.println(instant);    }}

计算时间间隔

  • Duration:计算两个时间之间的间隔
  • Period:计算两个日期之间的间隔
@Testpublic void test() {    Instant ins1 = Instant.now();    try {        Thread.sleep(1000);    } catch (InterruptedException e) {        e.printStackTrace();    }    Instant ins2 = Instant.now();    Duration duration = Duration.between(ins1, ins2);    System.out.println(duration.toMillis());    //  1009    LocalDate ld1 = LocalDate.of(2021,12,12);    LocalDate ld2 = LocalDate.now();    Period period = Period.between(ld1, ld2);    System.out.println(period.getYears());  // 0    System.out.println(period.getMonths()); // 0    System.out.println(period.getDays());   // 12    System.out.println();}

日期的操纵:
TemporalAdiuster :时间校正器。有时我们可能需要获取例如:将日期调整到“下个周日”等操作。

public class test {    @Test    public void test() {        LocalDateTime ldt = LocalDateTime.now();        LocalDateTime ldt2 = ldt.withDayOfMonth(10);    // 将日期设置为10        System.out.println(ldt);    // 2021-12-24T16:23:16.451        System.out.println(ldt2);   // 2021-12-10T16:22:40.417        LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));    // 下一个周日        System.out.println(ldt3);   // 2021-12-26T16:22:40.417        //自定义:下一个工作日志        LocalDateTime ldt5 = ldt.with( l -> {            LocalDateTime ldt4 = (LocalDateTime) l;            DayOfWeek dow = ldt4.getDayOfWeek();            if (dow.equals(DayOfWeek.FRIDAY)) {                return ldt4.plusDays(3);            } else if (dow.equals(DayOfWeek.SATURDAY)) {                return ldt4.plusDays(2);            } else{                return ldt4.plusDays(1);            }        });        System.out.println(ldt5);   // 2021-12-27T16:30:55.074    }}

DateTimeFORMatter:格式化时间/日期

@Testpublic void test() {    DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE;    LocalDateTime ldt = LocalDateTime.now();    String strDate = ldt.format(dtf);    System.out.println(strDate);    // 2021-12-24    DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");    String strDate2 = dtf2.format(ldt);    System.out.println(strDate2);   // 2021年12月24日 16:35:55    LocalDateTime newDate = LocalDateTime.parse(strDate2, dtf2);    System.out.println(newDate);    // 2021-12-24T16:38:58}

时区的处理

@Testpublic void test() {    LocalDateTime ldt = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));    System.out.println(ldt);    // 2021-12-24T10:43:37.135    LocalDateTime ldt2 = LocalDateTime.now(ZoneId.of("Europe/Tallinn"));    ZonedDateTime zdt = ldt2.atZone(ZoneId.of("Europe/Tallinn"));    System.out.println(zdt);    // 2021-12-24T10:45:08.507+02:00[Europe/Tallinn]}

来源地址:https://blog.csdn.net/m0_60915009/article/details/130637244

--结束END--

本文标题: Java 基础-Java8

本文链接: http://www.lsjlt.com/news/441872.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java 基础-Java8
    Java 8介绍 Java 8的主要新语法特性如下: Lambda表达式 Lambda表达式使Java程序员能够编写更加简洁、易读和易维护的代码。它是一种匿名函数,可以将其作为参数传递给其他方法或...
    99+
    2023-10-24
    java jvm 开发语言 JDK8 JAVA8
  • 【Java基础-JDK21新特性】它发任它发,我用java8
    💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想...
    99+
    2023-09-29
    java 开发语言
  • 【Java】Java基础
    环境准备 安装JDK和JRE 下载JDK,可以在官网Java Downloads | Oracle 中国下载,但是这里需要注册才能够下载。在Index of java-local/jdk (huawe...
    99+
    2023-09-22
    java
  • java 基础
    Now think about what happens if we run the same basic code but use a reference type instead of a primitive type: Point p...
    99+
    2023-06-03
  • Java8函数式接口的基础学习教程
    函数式接口 1.1 函数式接口概述 函数式接口:有且仅有一个抽象方法的接口 Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以使用与Lambda使用的接口 只...
    99+
    2024-04-02
  • Java 基础语法
    目录1、基本语法2、标识符(合法的变量名)3、关键字(保留字)4、注释5、Java 包5.1 package 语句5.2 import 语句6、源文件声明规则前言: Java 是一...
    99+
    2024-04-02
  • java 类基础(转)
    java 类基础(转)[@more@]类是Java 的核心和本质。它是Java 语言的基础,因为类定义了对象的本性。既然类是面向对象程序设计Java 语言的基础,因此,你想要在Java 程序中实现的每一个概念都必须封装在类以内。因为类是Ja...
    99+
    2023-06-03
  • Java 基础——Scanner 类
    目录 1.概述2.使用举例2.1.从不同的输入源读取数据2.2.next() 和 nextLine() 的区别2.3.读取大小已知的一维数组2.4.读取大小未知的一维数组2.5.读取长度大小已...
    99+
    2023-09-06
    Java Scanner 输入输出
  • Java 入门基础
    Java软件工程师是指运用Java这个开发工具去完成软件产品的软件程序设计、开发、测试、维护升级等工作的人员。::::::::::::::::::::::::::::::::::::::::::::::::::::::::Java 入门基础...
    99+
    2023-06-02
  • Java spring AOP基础
    目录一、AOP概述二、AOP相关语述三、AOP与动态代理3.1JDK动态代理3.2CGLib动态代理3.3两者对比总结一、AOP概述 AOP,即面向切面编程,简单来说就是将代码中重复...
    99+
    2024-04-02
  • Java基础语法
    文章目录 1. Java概述1.1 Java语言发展史1.2 Java语言跨平台原理1.3 JRE和JDK1.4 JDK的下载和安装1.4.1 下载1.4.2 安装1.4.3 JDK的安装目录介绍 2. 第一个演示程序2....
    99+
    2023-08-19
    intellij-idea java
  • Java基础-Java基本数据类型
    目录1 前言2 布尔类型3 字符类型4 值类型4.1 byte4.2 short4.3 int4.4 long4.5 float4.6 double5 码农来洞见5.1 类型转换5....
    99+
    2024-04-02
  • Day16基础不牢地动山摇-Java基础
    目录1、反射机制1.1 认识反射1.2 取得父类信息1.3 反射调用构造1.4 反射调用方法1.5 反射调用成员1.6 反射与简单Java类—单级VO操作原理1.7 单极自动VO设置...
    99+
    2024-04-02
  • Day14基础不牢地动山摇-Java基础
    目录1、定时器2、UUID类3、Base64加密处理加密处理多次加密4、ThreadLocal类5、IO—File类5.1 基本操作5.2 取得文件信息5.3 综合案例:目录列表6、...
    99+
    2024-04-02
  • java——多线程基础
    目录多线程使用场景:线程和进程区别:创建线程的方式:Thread类的有关方法:线程的同步:模拟火车站售票程序线程的同步:synchronized1. 同步代码块:2. synchro...
    99+
    2024-04-02
  • Java基础StringTokenizer用法
    StringTokenizer是Java中一个用于分割字符串的类,可以按照指定的分隔符将字符串分割成多个子串。使用StringTok...
    99+
    2023-09-23
    java
  • 【Java基础】- HttpURLConnection详解
    【Java基础】- HttpURLConnection详解 文章目录 【Java基础】- HttpURLConnection详解一、HttpURLConnection简述二、HttpURLCo...
    99+
    2023-09-09
    java servlet 开发语言 HttpURL
  • Java——基础语法(二)
    前言 「作者主页」:雪碧有白泡泡 「个人网站」:雪碧的个人网站 「推荐专栏」: ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄,vue成神之路★...
    99+
    2023-09-04
    java 开发语言
  • Java多线程基础
    目录一、线程二、创建多线程的方式1、继承Thread类实现多线程2、实现Runnable接口方式实现多线程3、Callable接口创建线程三、线程的生命周期与状态四、线程的执行顺序1...
    99+
    2024-04-02
  • Java-WebService基础使用
    Java WebService 是一种基于SOAP(Simple Object Access Protocol)协议的远程调用技术,...
    99+
    2023-09-23
    java
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作