話很少說,先打開源碼,查閱一番。尋得FunctionInterface接口html
package java.util.function; import java.util.Objects; /** * Represents a function that accepts one argument and produces a result. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #apply(Object)}. * * @param <T> the type of the input to the function * @param <R> the type of the result of the function * * @since 1.8 */ @FunctionalInterface public interface Function<T, R> { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); /** * Returns a composed function that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * * @see #andThen(Function) */ default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null * * @see #compose(Function) */ default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } /** * Returns a function that always returns its input argument. * * @param <T> the type of the input and output objects to the function * @return a function that always returns its input argument */ static <T> Function<T, T> identity() { return t -> t; } }
public class FunctionTest { public static void main(String[] args) { FunctionTest test = new FunctionTest(); // 傳遞行爲,而不是傳遞值 System.out.println(test.comput(1, value -> 2 * value)); System.out.println(test.comput(2, value -> 5 + value)); System.out.println(test.comput(3,Integer::intValue)); System.out.println(test.convert(4,value -> value + "helloworld")); } public int comput(int a, Function<Integer, Integer> function) { //apply ,傳遞的是行爲 int result = function.apply(a); return result; } public String convert(int a, Function<Integer, String> function) { return function.apply(a); } // 對於以前只傳遞值的寫法,幾種行爲就要定義幾種寫法。 如今可使用上面的方式去 傳遞行爲 public int method1(int a) { return a + 1; } public int method2(int a) { return a * 5; } public int method3(int a) { return a * a; } }
高階函數:若是一個函數接收一個函數做爲參數,或者返回一個函數做爲返回值,那麼該函數就叫作高階函數。函數式編程語言js等語言裏面都支持大量的高階函數,JAVA從1.8開始也開始支持高階函數。java
package java.util.function; import java.util.Objects; /** * Represents a function that accepts one argument and produces a result. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #apply(Object)}. * * @param <T> the type of the input to the function * @param <R> the type of the result of the function * * @since 1.8 */ @FunctionalInterface public interface Function<T, R> { /** * Applies this function to the given argument. * * @param t the function argument * @return the function result */ R apply(T t); /** * Returns a composed function that first applies the {@code before} * function to its input, and then applies this function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of input to the {@code before} function, and to the * composed function * @param before the function to apply before this function is applied * @return a composed function that first applies the {@code before} * function and then applies this function * @throws NullPointerException if before is null * 先應用beforefunction,再應用實例的function 實際上:將兩個function組合在一塊兒了。先執行before方法,而後將處理的結果傳遞給當前對象的apply方法。實現了兩個function的串聯。既然實現了兩個function的串聯,就能實現多個函數的串聯。 * @see #andThen(Function) */ default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); } /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null 和before函數相反,先應用this function,而後再使用after方法。 實現兩個方法的串聯。 * @see #compose(Function) */ default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); } /** * Returns a function that always returns its input argument. * * @param <T> the type of the input and output objects to the function * @return a function that always returns its input argument */ static <T> Function<T, T> identity() { return t -> t; } }
這些方法都是頗有價值的。編程
/** * compose , andThen 方法的使用 */ public class FunctionTest2 { public static void main(String[] args) { FunctionTest2 test2 = new FunctionTest2(); int compute = test2.compute(2, v -> v * 3, v -> v * v);//12 int compute2 = test2.compute2(2, v -> v * 3, v -> v * v);//36 System.out.println(compute); System.out.println(compute2); } public int compute(int a, Function<Integer, Integer> function1, Function<Integer, Integer> function2) { return function1.compose(function2).apply(a); } public int compute2(int a, Function<Integer, Integer> function1, Function<Integer, Integer> function2) { return function1.andThen(function2).apply(a); } }
package java.util.function; import java.util.Objects; /** * Represents a function that accepts two arguments and produces a result. * This is the two-arity specialization of {@link Function}. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #apply(Object, Object)}. * * @param <T> the type of the first argument to the function * @param <U> the type of the second argument to the function * @param <R> the type of the result of the function * * @see Function * @since 1.8 */ @FunctionalInterface public interface BiFunction<T, U, R> { /** * Applies this function to the given arguments. * * @param t the first function argument * @param u the second function argument * @return the function result */ R apply(T t, U u); /** * Returns a composed function that first applies this function to * its input, and then applies the {@code after} function to the result. * If evaluation of either function throws an exception, it is relayed to * the caller of the composed function. * * @param <V> the type of output of the {@code after} function, and of the * composed function * @param after the function to apply after this function is applied * @return a composed function that first applies this function and then * applies the {@code after} function * @throws NullPointerException if after is null */ 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類,雙向接口類,提供了兩個輸入參數,一個輸出參數app
//BiFunction類的使用。 有兩個輸入參數 public int compute3(int a, int b, BiFunction<Integer, Integer, Integer> biFunction) { return biFunction.apply(a, b); } public int compute4(int a, int b, BiFunction<Integer, Integer, Integer> biFunction,Function<Integer,Integer> function) { return biFunction.andThen(function).apply(a,b); } //使用BiFunction來完成 System.out.println(test2.compute3(1,2,(value1,value2)-> value1 + value2)); System.out.println(test2.compute3(1,2,(value1,value2)-> value1 - value2)); System.out.println(test2.compute3(1, 2, (value1, value2) -> value1 * value2)); System.out.println(test2.compute3(1, 2, (value1, value2) -> value1 / value2)); //使用BiFunction中的andThen. System.out.println(test2.compute4(2,3,(value1,value2)->value1+value2,value->value*value));
爲何BiFunction類中沒有Compose方法呢?編程語言
倒推一下:由於若是有Compose方法,會先執行參數的Function。不管參數是Function仍是BiFunction,返回值也都是一個值,而後就沒辦法再去執行BiFuntion.ide
定義一個簡單的Person類,而後使用lambda表達式解決一些問題 public class Person { private String username; private int age; }
package com.dawa.jdk8; import java.util.Arrays; import java.util.List; import java.util.function.BiFunction; import java.util.stream.Collectors; public class PersonTest { public static void main(String[] args) { Person person1 = new Person("zhangsan", 20); Person person2 = new Person("lisi", 30); Person person3 = new Person("wangwu", 40); List<Person> list = Arrays.asList(person1,person2,person3); PersonTest test = new PersonTest(); //測試第一個方法。 List<Person> list1 = test.getPersonByUsername("zhangsan", list); list1.forEach(person -> System.out.println(person.getUsername())); //測試第二種方法 List<Person> personByAge = test.getPersonByAge(20, list); personByAge.forEach(person -> System.out.println(person.getAge())); //測試第三方法 List<Person> peopleList = test.getPersonByArg(20, list, (age, personList) -> personList.stream().filter(p erson -> person.getAge() > age).collect(Collectors.toList())); peopleList.forEach(person -> System.out.println(person.getUsername())); } //使用lambda表達式定義一個 處理的方法 //filter 方法,參數是一個Predicate 謂語 //stream 提供了一個將流轉換成集合的方法 collect(Collectors.toList()) public List<Person> getPersonByUsername(String username, List<Person> personList) { return personList.stream(). filter(person -> person.getUsername().equals("zhangsan")).collect(Collectors.toList()); } //第二種方式,先直接使用lambda表達式將BiFunction定義好,而後直接將方法的兩個參數傳入到BiFunction. public List<Person> getPersonByAge(int age, List<Person> personList) { BiFunction<Integer, List<Person>, List<Person>> biFunction = (ageArg, Persons) -> { return Persons.stream().filter(person -> person.getAge() > ageArg).collect(Collectors.toList()); }; return biFunction.apply(age,personList); } //第三種方式,動做也讓他本身傳遞。 函數式接口的好處。 public List<Person> getPersonByArg(int age, List<Person> personList, BiFunction<Integer, List<Person>, List<Person>> biFunction) { return biFunction.apply(age, personList); } }
真諦:函數式接口,傳遞的是行爲,而不是數據。函數式編程
package java.util.function; import java.util.Objects; /** * Represents a predicate (boolean-valued function) of one argument. * * <p>This is a <a href="package-summary.html">functional interface</a> * whose functional method is {@link #test(Object)}. * * @param <T> the type of the input to the predicate * * @since 1.8 */ @FunctionalInterface public interface Predicate<T> { /** * Evaluates this predicate on the given argument. * * @param t the input argument * @return {@code true} if the input argument matches the predicate, * otherwise {@code false} */ boolean test(T t); /** * Returns a composed predicate that represents a short-circuiting logical * AND of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code false}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ANDed with this * predicate * @return a composed predicate that represents the short-circuiting logical * AND of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } /** * Returns a predicate that represents the logical negation of this * predicate. * * @return a predicate that represents the logical negation of this * predicate */ default Predicate<T> negate() { return (t) -> !test(t); } /** * Returns a composed predicate that represents a short-circuiting logical * OR of this predicate and another. When evaluating the composed * predicate, if this predicate is {@code true}, then the {@code other} * predicate is not evaluated. * * <p>Any exceptions thrown during evaluation of either predicate are relayed * to the caller; if evaluation of this predicate throws an exception, the * {@code other} predicate will not be evaluated. * * @param other a predicate that will be logically-ORed with this * predicate * @return a composed predicate that represents the short-circuiting logical * OR of this predicate and the {@code other} predicate * @throws NullPointerException if other is null */ default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } /** * Returns a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)}. * * @param <T> the type of arguments to the predicate * @param targetRef the object reference with which to compare for equality, * which may be {@code null} * @return a predicate that tests if two arguments are equal according * to {@link Objects#equals(Object, Object)} */ static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }
boolean test(T t)
給定一個輸入參數,判斷是否知足條件。知足則返回true,不知足返回false。package com.dawa.jdk8; import java.util.function.Predicate; public class PreDicateTest { public static void main(String[] args) { Predicate<String> predicate = p -> p.length() > 5; System.out.println(predicate.test("hello")); } }
這個接口會在流stream
裏面獲得大量的運用。上述案例在 stream的 filter()
方法參數中使用。函數
到如今爲止,Function包下的接口已經基礎了兩個了。
但是隻是講了幾個特別重要的接口,其餘的接口是沒時間一個一個講的。測試
這個時候我去看了一下源碼,發現JAVA8底層源碼,大量的使用函數接口來進行實現。
ui
道阻且長。~ 加油。 2019年12月29日22:18:25。明天就要上班了,今晚早點休息。