一、集合遍历与Lambda表达式 引入package com.java.design.java8;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.test.context.junit4.SpringRunner;import java.util.*;import java.util.function.Consumer;/** * @author 陈杨 */@RunWith(SpringRunner.class)@SpringBootTestpublic class ErgodicList { @Test public void testErgodicList() { // 直接构造集合对象 保证了集合size>0 List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 0); System.out.println("—————————传统for循环——————–\n"); for (int i = 0; i < list.size(); i++) { System.out.println(list.get(i)); } System.out.println("—————————增强for循环——————–\n"); for (Integer i : list) { System.out.println(i); } System.out.println("—————————迭代器————————-\n"); Iterator<Integer> iterator = list.iterator(); while (iterator.hasNext()) { Integer integer = iterator.next(); System.out.println(integer); } System.out.println("—————————forEach————————\n"); list.forEach(new Consumer<Integer>() { @Override public void accept(Integer integer) { System.out.println(integer); } });二、 @FunctionalInterface函数式接口与Lambda表达式1、概念// Consumer @FunctionalInterface函数式接口// Conceptually, a functional interface has exactly one abstract method.// 从概念上看,一个函数式接口有且只有一个精确的抽象方法// 从java8开始 接口中不仅仅存在抽象方法 还能存在有具体实现的方法(默认方法)2、 函数式接口的区分// Since {@linkplain java.lang.reflect.Method#isDefault()// default methods} have an implementation, they are not abstract. If// an interface declares an abstract method overriding one of the// public methods of {@code java.lang.Object}, that also does// <em>not</em> count toward the interface’s abstract method count// since any implementation of the interface will have an// implementation from {@code java.lang.Object} or elsewhere.// 因为java.lang.reflect.Method#isDefault() default methods 有一个实现 所以不是抽象的// 如果一个接口声明一个抽象方法,其实现了java.lang.Object类中public方法:不计入抽象方法的个数3、函数式接口的实例化方式// Note that instances of functional interfaces can be created with// lambda expressions, method references, or constructor references.// 函数式接口的实例化: lambda表达式 方法引用 构造方法引用4、函数式接口中的默认方法// default void forEach(Consumer<? super T> action) {// Objects.requireNonNull(action);// for (T t : this) {// action.accept(t);// }// }// action 针对每个元素 执行的动作行为// default 修饰接口 已实现的默认方法5、总结与思考// 1、如果一个接口中有且只有一个抽象方法 则其为一个函数式接口// 2、如果一个接口上声明了@FunctionalInterface注解 则编译器会按照函数式接口的定义来要求该接口// If a type is annotated with this annotation type, compilers are// required to generate an error message unless:// (1)The type is an interface type and not an annotation type, enum, or class.// (2)The annotated type satisfies the requirements of a functional interface.// However, the compiler will treat any interface meeting the// definition of a functional interface as a functional interface// regardless of whether or not a {@code FunctionalInterface}// annotation is present on the interface declaration.// 3、如果接口上只有一个抽象方法,但我们没有对其加上@FunctionalInterface 编译器仍然将其看作函数式接口// 加上注解后 一目了然 如果没有满足强制性要求 则会抛出错误信息// 4、只有一个抽象方法的接口 有必要加上 @FunctionalInterface 如 Runnable接口// 5、所有的函数式接口 都可以使用lambda表达式 实现(表达易懂 简单)三、函数式接口实例化 之 Lambda表达式System.out.println("——————–lambda创建函数式接口实例—————\n");list.forEach(i -> { // 若能推断出i的类型 不需要声明 // 如不能推断出(Integer i)->{} System.out.println(i);});四、在排序过程中 Lambda表达式的 演变System.out.println("————————–lambda排序———————–\n");// Collections.sort(list, new Comparator<Integer>() {// @Override// public int compare(Integer o1, Integer o2) {// return o2.compareTo(o1);// }// });// Collections.sort(list,(String o1, String o2)->{return o2.compareTo(o1);});// Collections.sort(list, (o1, o2) -> { return o2.compareTo(o1); });// statement { return o2.compareTo(o1); }// expression o2.compareTo(o1)// Collections.sort(list,(String::compareTo));// Collections.sort(list,Collections.reverseOrder());Collections.sort(list, (o1, o2) -> o2.compareTo(o1));System.out.println(list);五、函数式接口实例化 之 方法引用System.out.println("——————–方法引用创建函数式接口实例————–\n");list.forEach(System.out::println); }}六、深入理解Lambda表达式// lambda表达式:// 1、从函数式编程角度来看:// lambda表达式为Java添加了函数式编程的新特性 函数升格成为一等公民// 在函数作为一等公民的语言 如Python中 lambda表达式为函数类型// 但在java中 lambda表达式是对象类型 依赖于函数式接口Functional Interface// 2、lambda表达式书写// lambda表达式形式 () -> {} 必需根据上下文确定其匿名函数类型 函数方法 -> 函数实现// () 省略 参数只有一个且类型可根据上下文推导// {} 省略 方法体主体只有一条语句,返回值类型与主体表达式(匿名函数)一致// 3、进一步理解lambda表达式// lambda表达式传递行为action 不仅仅是值的传递 (类比Node.js的事件驱动 与 回调函数callback)// lambda表达式替换前: 事先定义对象及所持有的方法 根据 “对象.方法” 进行方法的调用 预先定义好的action// lambda表达式替换后: {} 方法调用 R apply(T t); 事先不知道action 仅在调用时才知道 action// 提升抽象层次 API重用性 使用灵活