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) @SpringBootTest public 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); } });
一、概念java
// Consumer @FunctionalInterface函數式接口 // Conceptually, a functional interface has exactly one abstract method. // 從概念上看,一個函數式接口有且只有一個精確的抽象方法 // 從java8開始 接口中不單單存在抽象方法 還能存在有具體實現的方法(默認方法)
二、 函數式接口的區分spring
// 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方法:不計入抽象方法的個數
三、函數式接口的實例化方式express
// Note that instances of functional interfaces can be created with // lambda expressions, method references, or constructor references. // 函數式接口的實例化: lambda表達式 方法引用 構造方法引用
四、函數式接口中的默認方法編程
// default void forEach(Consumer<? super T> action) { // Objects.requireNonNull(action); // for (T t : this) { // action.accept(t); // } // } // action 針對每一個元素 執行的動做行爲 // default 修飾接口 已實現的默認方法
五、總結與思考app
// 一、若是一個接口中有且只有一個抽象方法 則其爲一個函數式接口 // 二、若是一個接口上聲明瞭@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. // 三、若是接口上只有一個抽象方法,但咱們沒有對其加上@FunctionalInterface 編譯器仍然將其看做函數式接口 // 加上註解後 一目瞭然 若是沒有知足強制性要求 則會拋出錯誤信息 // 四、只有一個抽象方法的接口 有必要加上 @FunctionalInterface 如 Runnable接口 // 五、全部的函數式接口 均可以使用lambda表達式 實現(表達易懂 簡單)
System.out.println("--------------------lambda建立函數式接口實例---------------\n"); list.forEach(i -> { // 若能推斷出i的類型 不須要聲明 // 如不能推斷出(Integer i)->{} System.out.println(i); });
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表達式爲Java添加了函數式編程的新特性 函數升格成爲一等公民 // 在函數做爲一等公民的語言 如Python中 lambda表達式爲函數類型 // 但在java中 lambda表達式是對象類型 依賴於函數式接口Functional Interface // 二、lambda表達式書寫 // lambda表達式形式 () -> {} 必需根據上下文肯定其匿名函數類型 函數方法 -> 函數實現 // () 省略 參數只有一個且類型可根據上下文推導 // {} 省略 方法體主體只有一條語句,返回值類型與主體表達式(匿名函數)一致 // 三、進一步理解lambda表達式 // lambda表達式傳遞行爲action 不單單是值的傳遞 (類比Node.js的事件驅動 與 回調函數callback) // lambda表達式替換前: 事先定義對象及所持有的方法 根據 「對象.方法」 進行方法的調用 預先定義好的action // lambda表達式替換後: {} 方法調用 R apply(T t); 事先不知道action 僅在調用時才知道 action // 提高抽象層次 API重用性 使用靈活