天天看點

jdk8函數式程式設計Predicate Supplier Consumer Function

以上四個都是函數式接口,對于這些接口,重要的是明白其存在的意義

jdk推出這些函數式接口的目的是為了進行函數式程式設計,由于lambda表達式的應用,我們在實際程式設計中可能感受不到這些接口的使用,但其實在鍊式程式設計的時候,我們大量應用了這些接口。例如stream中的一個map方法,我們自然而然的直到這是将原值轉換為另一個值,而我們在寫lambda表達式的時候,其可行就是因為函數式接口Function的存在,總的來說,在函數式接口中增加了函數的總量,而幾乎可以忽略類(接口)的存在,函數成了一等公民。

Predicate 一個語言函數接口,核心方法 boolean test(T t) 當然該接口還提供了預設的接口實作方法幫助進行鍊式程式設計預言,該接口隻是提供了一個jdk标準的filter方法,每進行一次鍊式調用,都會生成一個新的Predicate對象。 源碼:

@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);
    }
}
           

例子:

public class PredicateTest {
    @Test
    public void test() {
        Predicate<String> predicate = s -> "jsen".equals(s.toLowerCase());
        Consumer<Boolean> consumer = System.out::println;
        consumer.accept(predicate.test("jSen"));
        consumer.accept(predicate.test("jack"));
    }
}
           

Supplier Supplier是一個内容提供者,傳回指定類型的執行個體對象,核心方法 T get() ,也隻有這個方法。 源碼:

@FunctionalInterface
public interface Supplier<T> {
    T get();
}
           

例子:

public class SupplierTest {
    @Test
    public void test() {
        Supplier<Integer> supplier = new Random()::nextInt;
        Consumer<Integer> consumer = System.out::println;
        consumer.accept(supplier.get());
    }
}
           

Consumer 用于消費一個結果,核心方法void accept(T t) 同時提供 Consumer<T> andThen(Consumer<? super T> after) 實作鍊式調用,該方法對兩個Consumer調用accept後建立一個新的Consumer,也可以将其想象成對某個事件執行結束後的特點處理(回調)。 源碼:

@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); };
    }
}
           

例子:

public class ConsumerTest {
    @Test
    public void test() {
        Consumer<String> simplePrint = System.out::println;
        handler("jsen", simplePrint);
    }
    private void handler(String s, Consumer<String> c) {
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            c.accept(s);
        }
    }
}
           

Fuction 相當于一個有傳回結果的回調接口,核心方法 R apply(T t) ,從形式上看,function接口與Consumer接口唯一的差別在于他是有傳回值的,意味着它可以對結果不斷鍊式處理。 以下實作對String list中元素統計長度并輸出。 源碼:

@FunctionalInterface
public interface Function<T, R> {
    R apply(T t);
    default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
        Objects.requireNonNull(before);
        return (V v) -> apply(before.apply(v));
    }
    default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t) -> after.apply(apply(t));
    }
    static <T> Function<T, T> identity() {
        return t -> t;
    }
}
           

例子:

public class FunctionTest {
    @Test
    public void test() {
        List<String> names = Lists.newArrayList("jsen", "jack", "lucy", "smile");
        names.stream().map(String::length).forEach(System.out::println);
    }
}