• java8 新特性


    1、lambda表达式

    Lambda 是一个 匿名函数,我们可以把 Lambda 表达式理解为是 一段可以传递的代码(将代码像数据一样进行传递)。使用它可以写出更简洁、更灵活的代码。

    (1)语法

    Lambda 表达式:在Java 8 语言中引入的一种新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda操作符或 箭头操作符。它将 Lambda 分为两个部分:

    左侧:指定了 Lambda 表达式需要的参数列表

    右侧:指定了 Lambda 体,是抽象方法的实现逻辑,也即Lambda 表达式要执行的功能。

    语法格式一 : 无参,无返回值

    Rannable r1 = () -> {System.out.println("Hello Lanbda !");}

    语法格式二: :Lambda 需要一个参数,但是没有返回值。

    Cousumer con = (String str) -> {System.out.println("str");}

    语法格式三 : 数据类型可以省略 ,因为可由编译器推断得出,称为“类型推断”

    Cousumer con = (str) -> {System.out.println("str");}

    语法格式四: :Lambda 若只需要一个参数时, 参数的小括号可以省略

    Cousumer con = str -> {System.out.println("str");}

    语法格式五: :Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值

    Comparator com = (x,y) -> { System.out.println("实现函数式接口方法"); return Integer.compare(x,y); }

    语法格式六 :当Lambda 体只有一条语句时,return与大括号若有,都可以省略

    Comparator com = (x,y) -> Integer.compare(x,y);

    (2)类型推断

    Lambda表达式中无需指定类型,程序依然可以编译,这是因为 javac 根据程序的上下文,在后台推断出了参数的类型。Lambda 表达式的类型依赖于上下文环境,是由编译器推断出来的。这就是所谓的“类型推断”。

    (3)应用示例
    1. // 1.创建线程
    2. new Thread(() -> {
    3. // method run,do something
    4. }, "threadName").start();
    5. // 2.匿名类
    6. JButton show = new JButton("show");
    7. show.addActionListener(e -> {
    8. // method actionPerformed()
    9. });
    10. // 3.forEach迭代
    11. List features = Arrays.asList("Lambdas", "Default Method", "Stream API", "Date and Time API");
    12. features.forEach(System.out::println);
    13. // 4.map 和reduce
    14. List costBeforeTax = Arrays.asList(100, 200, 300, 400, 500, 600);
    15. costBeforeTax.stream().map(e -> e + 0.12 * e).forEach(System.out::print);
    16. double bill = costBeforeTax.stream().map(e -> e + 0.12 * e)
    17. .reduce((sum, cost) -> sum + cost).get();
    18. System.out.println(bill);
    19. // 5.过滤 filter 收集 collect
    20. List strs = Arrays.asList("abc", "defg", "hi", "jkmln");
    21. List filtered = strs.stream().filter(e -> e.length() > 2).collect(Collectors.toList());
    22. // 6.去重
    23. List nums = Arrays.asList(1 ,2, 3, 1, 4, 5, 2, 6, 8, 7, 6);
    24. nums = nums.stream().distinct().collect(Collectors.toList());
    25. // 7.计算最大值、最小值、平均值、总和
    26. List primes = Arrays.asList(2, 3, 5, 7, 11, 13, 17, 19, 23, 29);
    27. IntSummaryStatistics stats = primes.stream().mapToInt(e -> e).summaryStatistics();
    28. System.out.println("最大值:" + stats.getMax());
    29. System.out.println("最小值:" + stats.getMin());
    30. System.out.println("平均值:" + stats.getAverage());
    31. System.out.println("总和:" + stats.getSum());
    32. System.out.println("计数:" + stats.getCount());
    (4)限制

    lambda表达式有个限制,只能引用final和final局部变量,也就是说不能再lambda表达式内部修改定义再域外的变量。否则编译报错:

    2、函数式(Functional)接口

    只包含一个抽象方法的接口,称为 函数式接口。

    Lambda表达式就是一个函数式接口的实例。匿名实现类表示的现在都可以用Lambda表达式来写。

    java内置四大核心函数式接口:

    3、方法引用与构造器引用

     当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!

     方法引用可以看做是Lambda表达式深层次的表达。换句话说,方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。

     要求:实现接口的抽象方法的参数列表和返回值类型,必须与方法引用的方法的参数列表和返回值类型保持一致!

     格式:使用操作符 “::” 将类(或对象)与方法名分隔开来。如下三种主要使用情况:

    对象::实例方法名

    类::静态方法名

    类::实例方法

    1. // 方法引用 ClassName::methodName
    2. 如: Comparator com = (x,y) -> Integer.compare(x,y);
    3. 等同于: Comparator com = Integer::compare;
    4. // 构造器引用 ClassName::new
    5. 如: Function fun = (n) -> new MyClass(n);
    6. 等同于: Function fun = MyClass::new;
    7. //数组引用 type[] :: new
    8. 如: Function new Integer[n];
    9. 等同于: Functionnew;

    4、Stream API

    Stream 和 Collection 集合的区别:Collection 是一种静态的内存数据结构,而 Stream 是有关计算的。前者是主要面向内存,存储在内存中,后者主要是面向 CPU,通过 CPU 实现计算。

    ①Stream 自己不会存储元素。

    ②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。

    ③Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。

    Stream操作的三个步骤:

    创建Stream -> 中间操作 -> 终止操作(终端操作)

    (1)创建Stream
    1. // 方式1:通过集合
    2. //Java8 中的 Collection 接口被扩展,提供了两个获取流的方法:
    3. default Stream stream() : 返回一个顺序流
    4. default Stream parallelStream() : 返回一个并行流
    5. 例:
    6. List list = Arrays.asList(1, 2, 3, 4, 5);
    7. Stream integerStream = list.stream();
    8. // 方式2:通过数组
    9. // Java8 中的 Arrays 的静态方法 stream() 可以获取数组流:
    10. static Stream stream(T[] array): 返回一个流
    11. 重载形式,能够处理对应基本类型的数组:
    12. public static IntStream stream(int[] array)
    13. public static LongStream stream(long[] array)
    14. public static DoubleStream stream(double[] array)
    15. 例: IntStream stream = Arrays.stream(new int[]{1, 2, 3, 4, 5});
    16. // 方式3:通过Stream的of()
    17. public static Stream of(T... values) // 接收任意可变参数,返回一个流
    18. 例: Stream stringStream = Stream.of("AA", "BB", "CC");
    19. // 方式4: 创建无限流
    20. >迭代 public static Stream iterate(final T seed, final UnaryOperator f) >
    21. 生成 public static Stream generate(Supplier s)
    22. 例:
    23. // 迭代
    24. Stream stream = Stream.iterate(0, x -> x + 2); stream.limit(10).forEach(System.out::println);
    25. // 生成
    26. Stream stream1 = Stream.generate(Math::random); stream1.limit(10).forEach(System.out::println);

    (2)Stream的中间操作

    (2.1)筛选与切片

    1. Person p1 = new Person("tom", 11);
    2. Person p2 = new Person("jerry", 8);
    3. Person p3 = new Person("marry", 5);
    4. Person p4 = new Person("john", 14);
    5. ArrayList list = new ArrayList<>();
    6. list.add(p1);
    7. list.add(p2);
    8. list.add(p3);
    9. list.add(p4);
    10. // 过滤
    11. List collect = list.stream() .filter(p -> p.getAge() > 10).collect(Collectors.toList());
    12. // 去重
    13. Person p5 = new Person("john", 14);
    14. collect = list.stream() .distinct() .collect(Collectors.toList());
    15. // 截断
    16. collect = list.stream() .limit(2) .collect(Collectors.toList());
    17. // 跳过元素
    18. collect = list.stream() .skip(2) .collect(Collectors.toList());

    (2.2)映射

    1. List nameList = list.stream()
    2. .map(Person::getName)
    3. .collect(Collectors.toList()); // map()和flatMap类似于集合的add()和addAll(),后者会展开元素

    (2.3)排序

    1. // 自定义比较
    2. List sortedList = list.stream() .sorted((e1, e2) -> e1.getAge()-e2.getAge()) .collect(Collectors.toList());
    3. // 数值的比较方法
    4. sortedList = list.stream() .sorted((e1, e2) -> Integer.compare(e1.getAge(), e2.getAge())) .collect(Collectors.toList());
    5. // Comparator的静态比较方法
    6. sortedList = list.stream() .sorted(Comparator.comparingInt(Person::getAge)) .collect(Collectors.toList());
    (3)Stream的终止操作

    (3.1)匹配与查找

    1. boolean allMatch = list.stream().allMatch(e -> e.getAge() > 10);
    2. Optional first = list.stream().findFirst();
    3. list.stream().filter(e -> e.getAge() > 10).count();
    4. Optional max = list.stream() .filter(e -> e.getAge() > 10) .max(Comparator.comparingInt(Person::getAge));
    5. list.stream().filter(e -> e.getAge() > 10).forEach(System.out::println);

    (3.2)归约

    Optional reduce = list.stream() .map(Person::getAge) .reduce((e1, e2) -> e1 + e2);

    (3.3)收集

    (4)Collectors

    5、Optional类

    Optional 类(java.util.Optional) 是一个容器类,它可以保存类型T的值,代表这个值存在。或者仅仅保存null,表示这个值不存在。原来用 null 表示一个值不存在,现在 Optional 可以更好的表达这个概念。并且可以避免空指针异常。

    Optional提供很多有用的方法,这样我们就不用显式进行空值检测。

    创建Optional 类对象的方法:

     Optional.of(T t) : 创建一个 Optional 实例,t必须非空;

     Optional.empty() : 创建一个空的 Optional 实例

     Optional.ofNullable(T t) :t可以为null

    判断Optional 容器中是否包含对象:

     boolean isPresent() : 判断是否包含对象

     void ifPresent(Consumer consumer) :如果有值,就执行Consumer接口的实现代码,并且该值会作为参数传给它。

    获取Optional 容器的对象:

     T get(): 如果调用对象包含值,返回该值,否则抛异常

     T orElse(T other) :如果有值则将其返回,否则返回指定的other对象。

     T orElseGet(Supplier other) : :如果有值则将其返回,否则返回由Supplier接口实现提供的对象。

     T orElseThrow(Supplier exceptionSupplier) : :如果有值则将其返

    回,否则抛出由Supplier接口实现提供的异常。

    1. //使用Optional类的getGirlName():
    2. public String getGirlName2(Boy boy){
    3. Optional boyOptional = Optional.ofNullable(boy);
    4. //此时的boy1一定非空
    5. Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪丽热巴")));
    6. Girl girl = boy1.getGirl();
    7. Optional girlOptional = Optional.ofNullable(girl);
    8. //girl1一定非空
    9. Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));
    10. return girl1.getName();
    11. }

  • 相关阅读:
    TikTok运营做不起来?IP如何选择?
    Python深度学习实战-基于tensorflow.keras六步法搭建神经网络(附源码和实现效果)
    基于抽象语法树的神经网络模型(ASTNN)简介
    Linux进程通信——IPC、管道、FIFO的引入
    java毕业设计大学生备考平台Mybatis+系统+数据库+调试部署
    C++ 智能指针
    面试题 17.16. 按摩师
    HTML5新特性
    一个启动U盘装多系统引导,无需反复格式化,ISO/WIM等文件拷贝到U盘即可启动
    动态规划-矩阵连乘
  • 原文地址:https://blog.csdn.net/weixin_42529699/article/details/132714249