• JDK8-17新特性


    一、JDK8新特性:Lambda表达式

    1.Lambda表达式及其使用举例

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

    1. Comparator com1 =new Comparator(){
    2. @Override
    3. public int compare(Integer o1,Integer o2){
    4. return Integer.compare(o1,o2);
    5. }
    6. };
    7. Comparatorcom2 = (Integer o1,Integer o2)->{
    8. return Integer.compare(o1,o2);
    9. };

    (1)lambda表达式使用:

    1. ->:lambda操作符或箭头操作符
    2. ->的左边:lambda形参列表,对应着要重写的接口中的抽象方法的形参列表,由一对小括号表示
    3. ->的右边:lambda体,对应着接口的实现类要重写的方法的方法体,由一对中括号表示
    4. 形参列表中的数据类型可以省略,因为可由编译器推断得出,称为"类型推断"
    5. lambda表达式若只需要一个参数时形参列表的小括号可以省略
    6. lambda体只有一条语句时return与大括号都可以省略,两个需要同时省略

    (2)lambda表达式的本质:

    a.lambda表达式作为接口的实现类的对象;

    b.lambda表达式是一个匿名函数

    2.函数式接口:

    (1)概念:如果接口中只声明一个抽象方法,则此接口称为函数式接口;因为只有给函数式接口提供实现类的对象时才可以使用lambda表达式;

    (2)API中函数式接口所在的包:java.util.function

    (3)4个基本的函数式接口

    函数式接口称谓参数类型用途
    Consumer消费型接口T对类型为T的对象应用操作,包含方法:void accpet(T t)
    Supplier供给型接口返回类型为T的对象,包含方法:T get()
    Function函数型接口T对类型为T的对象应用操作,并返回结果。结果是R类型的对象,包含方法:R apply(T t)
    Predicate判断型接口T确定类型为T的对象是否满足某种约束,并返回boolean值,包含方法:boolean test(T t)

    (4)消费型接口:有形参,但是返回值为void

    接口名抽象方法描述
    BiConsumervoid accept(T t,U u)接收两个对象用于完成功能
    DoubleConsumervoid accept(double value)接收一个double值
    IntConsumervoid accept(int value)接收一个int值
    LongConsumervoid accept(long  value)接收一个long值
    ObjDoubleConsumervoid accept(T t,double value)接收一个对象和一个double值
    ObjIntConsumervoid accept(T t,int value)接收一个对象和一个int值
    ObjLongConsumervoid accept(T t,long value)接收一个对象和一个long值

    (5)供给型接口:无形参,有返回值

    接口名抽象方法描述
    BooleanSupplierboolean getAsBoolean()返回一个boolean值
    DoubleSupplierdouble getAsDouble()返回一个double值
    IntSupplierint getAsInt()返回一个int值
    LongSupplierlong getAsLong()返回一个long值

    (6)函数型接口:既有参数也有返回值

    接口名抽象方法描述
    UnaryOperatorT apply(T t)接收一个T类型对象,返回一个T类型结果
    DoubleFunctionR apply(double value)接收一个double值,返回一个R类型结果
    IntFunctionR apply(int value)接收一个int值,返回一个R类型结果
    LongFunctionR apply(long value)接收一个long值,返回一个R类型结果
    ToDoubleFunctiondouble applyAsDouble(T value)接收一个T类型对象,返回一个double结果
    ToIntFunctiondouble applyAsInt(T value)接收一个T类型对象,返回一个int结果
    ToLongFunctiondouble applyAsLong(T value)接收一个T类型对象,返回一个long结果
    DoubleToIntFunctionint applyAsInt(double value)接收一个double值,返回一个int结果
    DoubleToLongFunctionint applyAsLong(double value)接收一个double值,返回一个long结果
    IntToDoubleFunctionint applyAsDouble(int value)接收一个int值,返回一个double结果
    LongToDoubleFunctionint applyAsDouble(long value)接收一个long值,返回一个double结果
    IntToLongFunctionint applyAsLong(int value)接收一个int值,返回一个long结果
    LongToIntFunctionint applyAsInt(long value)接收一个long值,返回一个int结果
    BinaryOperatorT apply(T t,T u)接收两个T类型对象,返回一个T类型对象结果
    ToDoubleBiFunctiondouble applyAsDouble(T t,U u)接收一个T类型和一个U类型对象,返回一个double
    ToLongBiFunctiondouble applyAsLong(T t,U u)接收一个T类型和一个U类型对象,返回一个long
    DoubleBinaryOperatordouble applyAsDouble(double d1,double d2)接收两个double值,返回一个double值
    ToIntBiFunctiondouble applyAsInt(T t,U u)接收一个T类型和一个U类型对象,返回一个int
    IntBinaryOperatorint applyAsInt(int i1,int i2)接收两个int值,返回一个int值
    LongBinaryOperatorlong applyAsLong(long l1,long l2)接收两个long值,返回一个long值

    (7)判断型接口:有形参,返回值是boolean的结果

    接口名抽象方法描述
    BiPredicateboolean test(T t,U u)接收两个对象
    DoublePredicateboolean test(double value)接收一个double值
    IntPredicateboolean test(int value)接收一个int值
    LongPredicateboolean test(long value)接收一个long值

    3.Lambda表达式的语法规则:

    1. ->:lambda操作符或箭头操作符
    2. 1.->的左边:lambda形参列表,对应着要重写的接口中的抽象方法的形参列表,由一对小括号表示
    3. 参数的类型都可以省略;如果形参只有一个则一对()也可以省略;
    4. 2.->的右边:lambda体,对应着接口的实现类要重写的方法的方法体,由一对{}表示
    5. 如果方法体中只有一条执行语句则{}可以省略;如果有return关键字则必须一并省略;

    二、方法引用

    1.方法引用的理解:

    (1)方法引用可以看作是Lambda表达式的进一步刻画;

    (2)当需要提供一个函数式接口的实例时可以使用lambda表达式提供此实例;

    (3)当满足一定的条件的情况下还可以使用方法引用或构造器引用替换lambda表达式;

    2.方法引用的本质:方法引用作为了函数式接口的实例

    3.使用格式:

    1. 类(或对象)::方法名
    2. 情况1:对象名::实例方法名
    3. 函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的形参列表和返回值类型都相同,
    4. 此时可以考虑使用方法b实现对方法a的替换、覆盖;此方法b是非静态的方法、需要对象调用;
    5. 情况2:类名::静态方法名
    6. 函数式接口中的抽象方法a与其内部实现时调用的类的某个静态方法b的形参列表和返回值类型都一致,
    7. 此时可以考虑使用方法b实现对方法a的替换、覆盖;此方法b是静态的方法、需要类调用;
    8. 情况3:类名::实例方法名
    9. 函数式接口中的抽象方法a与其内部实现时调用的对象的某个方法b的返回值类型相同;
    10. 同时抽象
    11. 方法a中有n个参数,方法b中有n-1个参数,且抽象方法a的第一个参数为方法b的调用者并且抽象方法a的后n-1个参数的类型相同或一致,此时可以考虑使用方法b实现对方法a的替换、覆盖;
    12. 此方法b是非静态的方法,需要对象调用,但是形式上写成对象a所属的类;

    三、构造器引用

    1.格式:

    类名::new

    2.说明:

    (1)调用了类名对应的类中的某一个确定的构造器;

    (2)具体调用的构造器取决于函数式接口的抽象方法的形参列表;

    四、StreamAPI:

    1.说明:

    Stream API(java.util.stream)把真正的函数式编程风格引入到Java中。这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。Stream是Java8中处理集合的关键抽象概念,可以指定希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。使用Stream API 对集合数据进行操作就类似于使用 SQL执行的数据库查询。也可以使用Stream API来并行执行操作。简言之Stream API提供了一种高效且易于使用的处理数据的方式。

    2.Stream API与集合框架的对比:

    (1)Stream API关注的是多个数据的计算(排序、查找、过滤、映射、遍历等)是面向CPU的,集合关注的数据的存储是面向内存的;

    (2)Stream API之于集合类似于SQL之于数据表的查询;

    3.注意事项:

    (1)Stream自己不会存储元素

    (2)Stream不会改变源对象。相反会返回一个持有结果的新Stream。

    (3)Stream操作是延迟执行的。这意味着会等到需要结果的时候才执行。即一旦执行终止操作,就执行中间操作链,并产生相应的结果;

    (4)Stream一旦执行了终止操作就不能再调用其它中间操作或终止操作;

    4.Stream执行流程:

    1. 1.Stream实例化
    2. (1)通过集合获取Stream的实例:
    3. a.default Stream stream():返回一个顺序流
    4. b.default Stream parallelStream():返回一个并行流
    5. (2)通过数组获取Stream的实例:
    6. a.Arrays工具类中的方法:static Stream stream(T[] array);
    7. (3)通过Stream类中的静态of()方法
    8. 2.一系列的中间操作
    9. 每次处理都会返回一个持有结果的新Stream,即中间操作的方法返回值仍然是Stream类型的对象;
    10. 因此中间操作可以是个操作链,可对数据源的数据进行n次处理,但是在终结操作前并不会真正执行;
    11. (1)筛选与切片
    12. a.filter(Predicatep):接收Lambda,从流中排除某些元素;
    13. b.distinct():筛选,通过流所生成元素的hashCode()和equals()去除重复元素;
    14. c.limit(long maxSize):截断流,使其元素不超过给定数量;
    15. d.skip(long n):跳过元素,返回一个扔掉了前n个元素的流;若流中元素不足n个则返回一个空流,与limit(n)互补;
    16. (2)映射:
    17. a.map(Function f):接收一个函数作为参数,该函数会应用到每个元素并将其映射成一个新的元素;
    18. b.mapToDouble(ToDoubleFunction f):接收一个函数作为参数,该函数会应用到每个元素上,产生一个新的DoubleStream;
    19. c.mapToInt(ToIntFunction f):接收一个函数作为参数,该函数会应用到每个元素上产生一个新的IntStream;
    20. d.mapToLong(ToLongFunction f):接收一个函数作为参数,该函数会应用到每个元素上产生一个新的LongStream;
    21. e.flatMap(Function f):接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流;
    22. (3)排序:
    23. a.sorted():产生一个新流,其中按自然顺序排序;
    24. b.sorted(Comparator com):产生一个新流,其中按比较器顺序排序;
    25. 3.终止操作
    26. 终止操作的方法返回值类型就不再是Stream了,因此一旦执行终止操作就结束整个stream操作;
    27. 一旦执行终止操作就执行中间操作链,最终产生结果并结束Stream;
    28. (1)匹配与查找:
    29. a.allMatch(Predicate p):检查是否匹配所有元素
    30. b.anyMatch(Predicate p):检查是否至少匹配一个元素
    31. c.noneMatc(Predicate p):检查是否没有匹配所有元素
    32. d.findFirst():返回第一个元素
    33. e.findAny():返回当前流中的任意元素
    34. f.count():返回流中元素总数
    35. g.max(Comparator c):返回流中最大值
    36. h.min(Comparator c):返回流中最小值
    37. i.forEach(Consumer c):内部迭代(使用Collection接口需要用户去做选代,称为外部迭代.相反,Stream API使用内部迭代)
    38. (2)规约:
    39. a.reduce(T identity, BinaryOperator b):可以将流中元素反复结合起来得到一个值,返回T;
    40. b.reduce(Binaryoperator b):可以将流中元素反复结合起来得到一个值,返回Optional
    41. (3)收集:
    42. collect(Collector c):将流转换为其他形式,接收一个Collector接口的实现,用于给Stream中元素做汇总的方法;

  • 相关阅读:
    荣耀的野望:智慧世界的“高端平民”
    网络常见的小知识点
    【Java从入门到精通】这也许就是Java火热的原因吧!
    Python Requests批量下载音频
    Spring:AOP通知获取数据(13)
    SpringBoot综合案例——Dubbo-Zookeeper-MyBatis-MySQL-Redis
    VSCode新建Vue项目
    机器学习算法基础--K-means聚类方法
    reticulate | R-python调用 | 安装及配置 | conda文件配置
    Git企业开发级讲解(五)
  • 原文地址:https://blog.csdn.net/m0_50460160/article/details/139698847