java8的大多數函數式接口都在java.util.function
包下。java
@FunctionalInterface public interface Consumer<T> { void accept(T t); default Consumer<T> andThen(Consumer<? super T> after) { Objects.requireNonNull(after); return (T t) -> { accept(t); after.accept(t); }; } }
Function函數會獲得一個參數,並返回一個結果,函數的方法是
void apply();
若是一個函數,接收一個函數做爲參數,或者返回一個函數做爲返回值,那麼這個函數就叫作高階函數。app
R apply(T t);
apply的語義爲:將函數應用到給定的參數上,T爲函數的輸入類型,R爲函數的返回類型函數
public int compute(int a, Function<Integer, Integer> function){ return function.apply(a); } public String convert(int a, Function<Integer, Integer> function){ return function.apply(a); } compute(1, value -> 2 * value); convert(5, value -> String.valueOf(value + helloworld)); Function<Integer, Integer> function = value -> value * value; compute(5,function);
Function不須要在設計時考慮到全部的行爲,在使用的時候,用戶能夠按照本身的思考來傳遞行爲,在調用前根本就不須要知道行爲是什麼。ui
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); }
compose組合
函數首先對輸入應用before
Function,而後再應用當前函數。是實際上造成了兩個function的串聯。this
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); }
andThen
與compose
正好相反,是先對輸入應用this.apply,而後再應用參數的after
Function。設計
Function
中的andThen
與compose
實際上是爲了實現一種業務場景:須要屢次調用某幾個Function,而Function.apply直接將結果返回,andThen
與compose
返回的依舊是Function。code
BiFunction
其實就是Function的一種強化版,能夠同時接受兩個參數進行操做,並返回一個結果。對象
R apply(T t, U u);
接受 T 和 U ,返回 R繼承
public compute(int a, int b, BiFunction<Integer, Integer, Integer> biFuncion){ return biFunction.apply(a, b); } test.compute(1, 2, (value1, value2) -> value1 + value2);
default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t, U u) -> after.apply(apply(t, u)); }
有意思的是,BiFunction的andThen方法,參數是Function而不是BiFunction。這是因爲:andThen的語義爲先執行this.apply,即BiFunction的apply,因爲BiFunction的apply返回結果只有一個值R
,而這個值又是做爲參數傳入給after
,因爲BiFunction須要接受兩個參數,因此after
必須是隻須要接受一個參數的Function。
這也是BiFunction沒有compose
方法的主要緣由,由於不管BiFunction仍是Function,返回的結果只有一個,因此沒法應用到當前的BiFunction上。接口
public class Person{ private String userName; private int age; } public class Test{ public static void main(String[] args){ Person p1 = new Person("a", 10); Person p2 = new Person("b", 20); Person p3 = new Person("c", 30); List<Person> list = Arrays.asList(p1, p2, p3); Test test = new Test(); // List<Person> res1 = test.getPersonsByUserName("a", list); // List<Person> res2 = test.getPersonsByAge("a", list); List<Person> res3 = test.getPersonsByAge2(20, list, (age, personList) -> { return personList.stream().filter(person -> person.getAge() >= age).collect(Collectors.toList()); }); List<Person> res4 = test.getPersonsByAge2(20, list, (age, personList) -> { return personList.stream().filter(person -> person.getAge() < age).collect(Collectors.toList()); }); } // 方式一,經過流的filter public List<Person> getPersonsByUserName(String userName, List<Person> persons){ return persons.stream().filter(person -> person.getUserName().equals(userName)).collect(Collectors.toList()); } // 方式二,經過BiFunctionb包裝 public List<Person> getPersonsByAge(int age, List<Person> persons){ BiFunction<Integer, List<Person>, List<Person>> biFunction = (a ,l) -> { return l.stream().filter(person -> person.getAge() >= a).collect(Collectors.toList()); }; return biFunction.apply(age, persons); } // 方式三,經過接收BiFunction public List<Person> getPersonsByAge2(int age, List<Person> persons, BiFunction<Integer, List<Person>, List<Person>> biFunction){ return biFunction.apply(age, persons); } }
若是經過方法三來實現,將方法的實現反轉給調用者,調用者能夠更靈活的規範他想要篩選數據的方式和條件。
@FunctionalInterface public interface Predicate<T> { boolean test(T t); default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } default Predicate<T> negate() { return (t) -> !test(t); } default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }
predicate接受一個參數,並返回一個boolean。
Predicate<String> predicate = p -> p.length() > 5; predicate.test("aaaaaa"); List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); conditionFilter(list, p -> p % 2 ==0); public void conditionFilter(List<Integer> list, Predicate<Integer> predicate){ list.forEach(i -> { if(predicate.test(i)){ System.out.println(i); } }) } // isEqual 方法使用 System.out.println(Predicate.isEqual("test").test("test"));
表示一個結果的供應者,並無要求提供與之前不一樣的結果。不接受任何參數,並返回一個結果。
public interface Supplier<T>{ T get(); }
在開發時supplier能夠用於工廠
,不接受參數並返回實例。
public class Student { private String name; private Intger age; } public class StudentTest{ // 經過supplier調用 student的構造方法 Supplier<Student> supplier = () -> new Student(); supplier.get().getName(); Supplier<Student> supplier2 = Student::new; supplier2.get().getName(); }
對於Supplier來講,須要不接受參數,而且返回結果。因此若是對象中沒有無參構造方法,編譯器則會報錯。
@FunctionalInterface public interface BinaryOperator<T> extends BiFunction<T,T,T> { public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) <= 0 ? a : b; } public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) { Objects.requireNonNull(comparator); return (a, b) -> comparator.compare(a, b) >= 0 ? a : b; } }
BinaryOperator
繼承了BiFunction
。可是BinaryOperator是一種特殊的BiFunction,它的三個類型都一致。
minBy
接受了一個Comparator函數式接口
,返回一個BinaryOperator類型對象,是兩個入參中更小的那個,判斷的標準來自於Comparator比較規則。maxBy則相反。
public class Test { public static void main(String[] args) { Test test = new Test(); System.out.println(test.cul("avv", "bbbbb", Comparator.comparingInt(String::length))); System.out.println(test.cul("avv", "bbbbb", (a, b) -> a.charAt(0) - b.charAt(0))); System.out.println(test.cul("avv", "bbbbb", Comparator.comparingInt(a -> a.charAt(0)))); } public String cul(String a, String b , Comparator<String> comparator){ return BinaryOperator.minBy(comparator).apply(a,b); } }
函數式接口是JDK8中的Stream和Optional等內容的基礎。以上這幾個是其餘函數式接口的基礎。