Java8两大最重要的改变:Lambda表达式和Stream API
集合讲的是数据,Stream讲的是计算!
1. Lambda 表达式
Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)
2. Lambda 表达式的介绍
-> :lambda操作符、箭头操作符
左边:lambda 形参列表(其实就是接口中的抽象方法的形参列表)
右边:lambda 体(其实就是重写的抽象方法的方法体)
3. Lambda 表达式的使用
分为 6 种语法介绍
格式一:无参、无返回值。Runnable r1 = () -> { System.out.println(" ..... ") ;};
格式二:Lambda 需要一个参数,但是没有返回值。Consumer<String> con = (String str) -> { System.out.println(str) ;};
格式三:数据类型可以省略 ,因为可由编译器推断得出,称为“类型推断”。
Consumer<String> con = (str) -> { System.out.println(str) ;};
格式四:Lambda 若只需要一个参数时, 参数的小括号可以省略。Consumer<String> con = str -> { System.out.println(str) ;};
格式五:Lambda 需要两个或以上的参数,多条执行语句,并且可以有返回值。
- Conparator<Integer> com = (x,y) -> {
- System.out.printLn("实现函数式接口方法!");
- return Integer.compare(x,y);
- }
格式六:当 Lambda 体只有一条语句时,return与大括号都可以省。
Conparator<Integer> com = (x,y) -> Integer.compare(x,y);
4. Lambda的本质是作为函数式接口的实例;
5. 总结
左边:lambda 形参列表的参数类型可以省略(类型推断);如果 lambda 形参列表只有一个参数,其一对()也可以省略;
右边:lambda 体应该使用一对 { } 包裹;如果 lambda 体只有一条执行语句(可能是return语句),可以省略这一对 { } 和 return 关键字;
6. 函数式接口:如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口;
- 可以通过 Lambda 表达式来创建该接口的对象。(若 Lambda 表达式抛出一个受检异常(即:非运行时异常),那么该异常需要在目标接口的抽象方法上进行声明)。
- 可以在接口上使用 @FunctionalInterface 注解,检查它是否是一个函数式接口。同时 javadoc 也会包含一条声明,说明这个接口是一个函数式接口。
- 在java.util.function包下定义了Java 8 的丰富的函数式接口
7. 内置四大核心函数式接口
8. 方法引用
① 使用情景:当要传递给 lambda 体的操作,已经有实现的方法了,可以使用方法引用。
② 方法引用本质上还是 lambda 表达式,而 lambda 表达式作为函数式接口的实例,所以方法引用也是函数式接口的实例;
③ 方法引用使用要求:要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同。
④ 使用格式:类(或对象)::方法名
具体可以分为3种情况:
情况一:对象::非静态方法
// 情况一 对象::实例方法(非静态方法,所以需要类去调用) // Consumer中的 void accept(T t) // PrintStream中的 void println(T t) Consumer<String> con1 = str -> System.out.println(str); con1.accept("beijing"); System.out.println("*************************"); Consumer<String> con2 = System.out::println; con2.accept("北京"); // Employee中的 String getName() // Supplier中的 T get() Employee emp = new Employee("jack", 5000, 2012, 10, 20); Supplier<String> sup1 = () -> emp.getName(); System.out.println(sup1.get()); System.out.println("*************************"); Supplier<String> sup2 = emp::getName; System.out.println(sup2.get());
情况二:类::静态方法
// 情况二 类::静态方法 // Comparator中的 int compare(T t1, T t2) // Integer中的 int compare(T t1, T t2) Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1, t2); System.out.println(com1.compare(12,24)); System.out.println("*************************"); Comparator<Integer> com2 = Integer::compare; System.out.println(com2.compare(12,24)); // Function中的 R apply(T t) // Math中的 Long round(Double d) Function<Double, Long> func = new Function<Double, Long>() { @Override public Long apply(Double d) { return Math.round(d); } }; Function<Double, Long> func1 = d -> Math.round(d); System.out.println(func1.apply(24.0)); System.out.println("*************************"); Function<Double, Long> func2 = Math::round; System.out.println(func1.apply(24.0));
情况三:类::非静态方法
// 情况三 类::实例方法 // Comparator中的 int compare(T t1, T t2) // String中的 int t1.compareTo(t2) Comparator<String> com1 = (s1, s2) -> s1.compareTo(s2); System.out.println(com1.compare("abc", "bcd")); System.out.println("*************************"); Comparator<String> com2 = String::compareTo; System.out.println(com2.compare("abc", "bcd")); // BiPredicate中的 boolean test(T t1, T t2) // String中的 boolean t1.equals(t2) BiPredicate<String, String> pre1 = (s1, s2) -> s1.equals(s2); BiPredicate<String, String> pre2 = String::equals; // Function中的 R apply(T t) // Employee中的 String getName() Employee employee = new Employee("jack", 5000, 2012, 10, 20); Function<Employee, String> func1 = e -> e.getName(); System.out.println(func1.apply(employee)); System.out.println("*************************"); Function<Employee, String> func2 = Employee::getName; System.out.println(func2.apply(employee));
9. 构造器引用和数组引用
构造器引用
和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致;
抽象方法的返回值类型即为构造器所属的类的类型;
数组引用:可以把数组看作一个特殊的类,写法与构造器引用一致;
// 构造器引用 // Supplier中的 T get() // Employee的无参构造器:Employee() Supplier<Employee> sup = new Supplier<Employee>() { @Override public Employee get() { return new Employee(); } }; Supplier<Employee> sup1 = () -> new Employee(); System.out.println("*************************"); Supplier<Employee> sup2 = Employee::new; // Function中的 R apply(T t) Function<Integer, Employee> func1 = id -> new Employee(id); Employee employee = func1.apply(1001); System.out.println("*************************"); Function<Integer, Employee> func1 = Employee::new; // Function中的 R apply(T t, U u) Function<Integer, String, Employee> func2 = (id,name) -> new Employee(id, name); Employee employee1 = func1.apply(1001, "ACX"); System.out.println("*************************"); Function<Integer, String, Employee> func3 = Employee::new;
10. Stream API
① Stream关注的是对数据的运算,与CPU打交道;集合关注的是数据的存储,与内存打交道;
② 注意点:
- Stream 自己不会存储元素。
- Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。
- Stream 操作是延迟执行的。这意味着他们会等到需要结果的时候才执行。
③ Stream 执行流程
stream实例化 ----> 一系列的中间操作(过滤、映射、...) ----> 终止操作
④ 说明
- 一个中间操作链,对数据源的数据进行处理
- 一旦执行终止操作,就执行中间操作链,并产生结果。之后,不会再被使用
11. Stream 实例化
创建
方式一:通过集合
-
-
- default Stream<E> stream() : 返回一个顺序流(拿数据的时候按顺序取)
- default Stream<E> parallelStream() : 返回一个并行流(类似多线程随机取)
-
方式二:通过数组(Java8 中的 Arrays 的静态方法 stream() 可以获取数组流)
-
-
- static <T> Stream<T> stream(T[] array): 返回一个流
-
方式三:通过Stream 的of()
-
-
- public static<T> Stream<T> of(T... values) : 返回一个流
-
方式四:创建无限流
-
-
- 迭代 public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
- 生成 public static<T> Stream<T> generate(Supplier<T> s)
-
中间操作
筛选与切片
List<Employee> empList = EmployeeData.getEmployees(); // filter(Predicate p)——接收 Lambda , 从流中排除某些元素 Stream<Employee> stream = empList.stream(); // 练习1 查询员工表中薪资大于7000的员工信息 stream.filter(e->e.getSalary() > 7000).forEach(System.out::println); // limit(n)——截断流,使其元素不超过给定数量 empList.stream().limit(3).forEach(System.out::println); // skip(n)——跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补 empList.stream().skip(3).forEach(System.out::println); // distinct()——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素 empList.stream().distinct().forEach(System.out::println);
映射
排序
终止操作
匹配与查找
归约
收集
12. Optional类:解决空指针问题;
标签:Java,Stream,System,Employee,days04,println,Lambda,宋红康,out From: https://www.cnblogs.com/LinxhzZ/p/16754391.html