Java8新特性

2021-02-23  本文已影响0人  DOB_8199

一、Lambda表达式

1. 举例

         (o1,o2) -> Integer.compare(o1,o2);

2. 格式:

      -> :lambda操作符 或 箭头操作符

      ->左边:lambda形参列表 (其实就是接口中的抽象方法的形参列表)

      ->右边:lambda体 (其实就是重写的抽象方法的方法体)

3. Lambda表达式的使用:

      ->左边:lambda形参列表的参数类型可以省略(类型推断);如果lambda形参列表只有一个参数,其一对()也可以省略

      ->右边:lambda体应该使用一对{}包裹;如果lambda体只有一条执行语句(可能是return语句),省略这一对{}和return关键字

4. Lambda表达式的本质:作为函数式接口的实例

5. 如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口。我们可以在一个接口上使用 @FunctionalInterface 注解,这样做可以检查它是否是一个函数式接口。

6. 所以以前用匿名实现类表示的现在都可以用Lambda表达式来写。

补充:

关于Supplier

java.util.function.Supplier 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。

二、方法引用

1.使用情境

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

2.方法引用本质

方法引用上就是Lambda表达式,而Lambda表达式作为函数式接口的实例。所以方法引用,也是函数式接口的实例。

3. 使用格式

  类(或对象) :: 方法名

 4. 具体分为如下的三种情况:

情况1    对象 :: 非静态方法

情况2    类 :: 静态方法

情况3    类 :: 非静态方法

5. 方法引用使用的要求

要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同!(针对于情况1和情况2)

补充

构造器引用

和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致。抽象方法的返回值类型即为构造器所属的类的类型

数组引用

大家可以把数组看做是一个特殊的类,则写法与构造器引用一致。

三、强大的Stream API

Stream实例化的方式

1. 通过集合

        List employees = EmployeeData.getEmployees();

    1) default Stream stream() : 返回一个顺序流

        Stream stream = employees.stream();

    2) default Stream parallelStream() : 返回一个并行流

        Stream parallelStream = employees.parallelStream();

2. 通过数组

        int[] arr =new int[]{1,2,3,4,5,6};

    调用Arrays类的static Stream stream(T[] array): 返回一个流

        IntStream stream = Arrays.stream(arr);

        Employee e1 =new Employee(1001,"Tom");

        Employee e2 =new Employee(1002,"Jerry");

        Employee[] arr1 =new Employee[]{e1,e2};

        Stream stream1 = Arrays.stream(arr1);

3. 通过Stream的of()

        Stream stream = Stream.of(1, 2, 3, 4, 5, 6);

4. 创建无限流

1) 迭代 public static Stream iterate(final T seed, final UnaryOperator f)

        遍历前10个偶数

        Stream.iterate(0, t -> t +2).limit(10).forEach(System.out::println);

2) 生成 public static Stream generate(Supplier s)

        生成十个随机数

        Stream.generate(Math::random).limit(10).forEach(System.out::println);

Stream的中间操作

1. 筛选与切片

        List list = EmployeeData.getEmployees();

1)filter(Predicate p)——接收 Lambda,从流中排除某些元素。

        Stream stream = list.stream();

        练习:查询员工表中薪资大于7000的员工信息

        stream.filter(e -> e.getSalary() >7000).forEach(System.out::println);

2)limit(n)——截断流,使其元素不超过给定数量。

        list.stream().limit(3).forEach(System.out::println);

3)skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补

        list.stream().skip(3).forEach(System.out::println);

4)distinct() ——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素

        list.stream().distinct().forEach(System.out::println);

2. 映射

1)map(Function f)——接收一个函数作为参数,将元素转换成其他形式或提取信息,该函数会被应用到每个元素上,并将其映射成一个新的元素。

        List list = Arrays.asList("aa", "bb", "cc", "dd");

        list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);

        练习1:获取员工姓名长度大于3的员工的姓名。

        List employees = EmployeeData.getEmployees();

        Stream namesStream = employees.stream().map(Employee::getName);

        namesStream.filter(name -> name.length() >3).forEach(System.out::println);

        练习2:

        Stream> streamStream = list.stream().map(StreamAPIMidTest::fromStringToStream);

        streamStream.forEach(s ->{s.forEach(System.out::println);});

        将字符串中的多个字符构成的集合转换为对应的Stream的实例

        public static StreamfromStringToStream(String str){//aa

            ArrayList list =new ArrayList<>();

            for(Character c : str.toCharArray()){

                list.add(c);}

            return list.stream();}

2)flatMap(Function f)——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流。

        Stream characterStream = list.stream().flatMap(StreamAPIMidTest::fromStringToStream);

        characterStream.forEach(System.out::println);

3. 排序

1)sorted()——自然排序

        List list = Arrays.asList(12, 43, 65, 34, 87, 0, -98, 7);

        list.stream().sorted().forEach(System.out::println);

2)sorted(Comparator com)——定制排序

        List employees = EmployeeData.getEmployees();

        employees.stream().sorted( (e1,e2) -> {

              int ageValue = Integer.compare(e1.getAge(),e2.getAge());

              if(ageValue !=0){

                    return ageValue;

               }else{

                    return -Double.compare(e1.getSalary(),e2.getSalary());}

      }).forEach(System.out::println);}


Stream终止操作

1. 匹配与查找

1)allMatch(Predicate p)——检查是否匹配所有元素。

        List employees = EmployeeData.getEmployees();

        练习:是否所有的员工的年龄都大于18

        boolean allMatch = employees.stream().allMatch(e -> e.getAge() >18);

        System.out.println(allMatch);

2)anyMatch(Predicate p)——检查是否至少匹配一个元素。

         练习:是否存在员工的工资大于 10000

        boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() >10000);

        System.out.println(anyMatch);

3)noneMatch(Predicate p)——检查是否没有匹配的元素。

          练习:是否存在员工姓“雷”

        boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startsWith("雷"));

        System.out.println(noneMatch);

4)findFirst——返回第一个元素

        Optional employee = employees.stream().findFirst();

        System.out.println(employee);

5)findAny——返回当前流中的任意元素

        Optional employee1 = employees.parallelStream().findAny();

        System.out.println(employee1);

6)count——返回流中元素的总个数

        long count = employee.stream().filter(e -> e.getSalary() >5000).count();

        System.out.println(count);

7)max(Comparator c)——返回流中最大值

        练习:返回最高的工资:

        Stream salaryStream = employees.stream().map(e -> e.getSalary());

        Optional maxSalary = salaryStream.max(Double::compare);

        System.out.println(maxSalary);

8)min(Comparator c)——返回流中最小值

        练习:返回最低工资的员工

        Optional employee = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));

        System.out.println(employee);

        System.out.println();

9)forEach(Consumer c)——内部迭代

        employees.stream().forEach(System.out::println);

        注:使用集合的遍历操作为外部迭代:

        employees.forEach(System.out::println);

2. 归约

1)reduce(T identity, BinaryOperator)——可以将流中元素反复结合起来,得到一个值。返回 T

        练习1:计算1-10的自然数的和

        List list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);

        Integer sum = list.stream().reduce(0, Integer::sum);

        System.out.println(sum);

2)reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。返回 Optional

        练习2:计算公司所有员工工资的总和

        List employees = EmployeeData.getEmployees();

        Stream salaryStream = employees.stream().map(Employee::getSalary);

        Optional sumMoney = salaryStream.reduce(Double::sum);

        Optional sumMoney = salaryStream.reduce((d1,d2) -> d1 + d2);

        System.out.println(sumMoney.get());

3. 收集

1)collect(Collector c)——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法

        练习1:查找工资大于6000的员工,结果返回为一个List或Set

        List employees = EmployeeData.getEmployees();

        List employeeList = employees.stream().filter(e -> e.getSalary() >6000).collect(Collectors.toList());

        employeeList.forEach(System.out::println);

        System.out.println();

        Set employeeSet = employees.stream().filter(e -> e.getSalary() >6000).collect(Collectors.toSet());

        employeeSet.forEach(System.out::println);}



四、Optional类

上一篇下一篇

猜你喜欢

热点阅读