package java.lang; import java.lang.annotation.*; /** * An informative annotation type used to indicate that an interface * type declaration is intended to be a <i>functional interface</i> as * defined by the Java Language Specification. * * Conceptually, a functional interface has exactly one abstract * method. 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. * * <p>Note that instances of functional interfaces can be created with * lambda expressions, method references, or constructor references. * * <p>If a type is annotated with this annotation type, compilers are * required to generate an error message unless: * * <ul> * <li> The type is an interface type and not an annotation type, enum, or class. * <li> The annotated type satisfies the requirements of a functional interface. * </ul> * <p>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. * * @jls 4.3.2. The Class Object * @jls 9.8 Functional Interfaces * @jls 9.4.3 Interface Method Body * @since 1.8 */ @Documented @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface FunctionalInterface {}
函數式接口只有一個抽象方法
因爲default方法有一個實現,因此他們不是抽象的.
若是一個接口定義了一個抽象方法,而他剛好覆蓋了Object的public方法,仍舊不算作接口的抽象方法, 由於它終將會在某處獲得一個實現.(若是不是public的那麼計數)
也便是隻有一個抽象方法默認不算,Object的public也不算
|
函數式接口的實例能夠經過 lambda表達式 方法引用 或者構造方法引用進行表示 |
類型必須是接口,而不能是其餘的好比class 並且須要符合函數式接口的定義要求 不然使用註解時編譯器報錯 |
無論他們是否有使用註解FunctionalInterface 進行註解, 編譯器將會把任何知足函數式接口定義的接口當作一個函數式接口 也就是說不加也行,可是顯然不加的話,就沒有限制約束,後續可能增長了其餘方法致使出錯 |
接口 抽象方法
|
java.util.function.Predicate<T>
斷言 也就是條件測試器 接收條件,進行測試
接口定義了一個名叫test的抽象方法,它接受泛型T對象,並返回一個boolean。
test (條件測試) , and-or- negate(與或非) 方法
|
java.util.function.Consumer<T>
消費者 消費數據 接收參數,返回void 數據被消費了
定義了一個名叫accept的抽象方法,它接受泛型T的對象,沒有返回(void)
你若是須要訪問類型T的對象,並對其執行某些操做,就可使用這個接口
|
java.util.function.Function<T, R>
函數 有輸入有輸出 數據轉換功能
接口定義了一個叫做apply的方法,它接受一個泛型T的對象,並返回一個泛型R的對象。
|
java.util.function.Supplier<T> 提供者 不須要輸入,產出T 提供數據 無參構造方法 提供T類型對象 |
接口中的compose, andThen, and, or, negate 用來組合函數接口而獲得更強大的函數接口
四大接口爲基礎接口,其餘的函數接口都是經過這四個擴展而來的
此處的擴展是指概念的展開 不是日常說的繼承或者實現,固然實現上多是經過繼承好比UnaryOperator
|
加了類型前綴[Int|Double|Long] 表示參數是基本類型, 若是在此基礎上又加上了To 表示返回類型是基本類型 |
(parameters) -> expression |
(parameters) -> { statements; } |
() -> {System.out.print("Hello");System.out.println(" World");};
class A { private String s1="a"; private String s2="b"; private String s3="c"; A(){ } A(String s1){ this.s1=s1; } A(String s1,String s2){ this.s1=s1; this.s2=s2; } A(String s1,String s2,String s3){ this.s1=s1; this.s2=s2; this.s3=s3; } @Override public String toString() { final StringBuilder sb = new StringBuilder("A{"); sb.append("s1='").append(s1).append('\''); sb.append(", s2='").append(s2).append('\''); sb.append(", s3='").append(s3).append('\''); sb.append('}'); return sb.toString(); } }
函數式接口 變量名 = Lambda-匿名函數/方法引用/構造方法引用; |
List<Integer> listNum = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); java
List filteredNum = listNum.stream().filter(i -> i.compareTo(5) < 0).collect(Collectors.toList()); web
System.out.println(filteredNum);
express
1. 經過形參類型或者變量類型 找到函數接口進而找到抽象方法的聲明
2. 而後在與參數值進行比對查看是否匹配
|
若是不一樣的函數接口,具備相互兼容的抽象方法簽名 那麼一個Lambda表達式顯然能夠匹配多個函數接口
|
特殊的void兼容規則
若是一個Lambda的主體是一個語句表達式, 它就和一個返回void的函數描述符兼容(固然須要參數列表也兼容)。
就是說 若是主體是一個語句,無論作什麼或者調用方法返回其餘的類型,他均可以兼容void
|
List<String> list= new ArrayList<>(); app
// Predicate返回了一個boolean less
Predicate<String> p = s -> list.add(s); ide
// Consumer返回了一個void 函數
Consumer<String> b = s -> list.add(s);
性能
List<String> list = new ArrayList<String>(); |
List<String> list = new ArrayList<>(); |
.filter((Integer i) -> { return i.compareTo(5) < 0;}).collect(Collectors.toList()); 測試
.filter((Integer i) ->i.compareTo(5) < 0).collect(Collectors.toList()); ui
.filter(i ->i.compareTo(5) < 0).collect(Collectors.toList());