Java8-6-Predicate接口詳解


轉自https://segmentfault.com/a/1190000012256677

Predicate函數式接口的主要作用就是提供一個test方法,接受一個參數返回一個布爾類型,Predicate在stream api中進行一些判斷的時候非常常用。

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

使用泛型T指定傳入的參數類型,我們通過一個根據不同條件取出不同數據的例子來看下Predicate具體應用

public class PredicateTest { public static void main(String[] args) { List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10); PredicateTest predicateTest = new PredicateTest(); //輸出大於5的數字
        List<Integer> result = predicateTest.conditionFilter(list, integer -> integer > 5); result.forEach(System.out::println); System.out.println("-------"); //輸出大於等於5的數字
        result = predicateTest.conditionFilter(list, integer -> integer >= 5); result.forEach(System.out::println); System.out.println("-------"); //輸出小於8的數字
        result = predicateTest.conditionFilter(list, integer -> integer < 8); result.forEach(System.out::println); System.out.println("-------"); //輸出所有數字
        result = predicateTest.conditionFilter(list, integer -> true); result.forEach(System.out::println); System.out.println("-------"); } //高度抽象的方法定義,復用性高
    public List<Integer> conditionFilter(List<Integer> list, Predicate<Integer> predicate){ return list.stream().filter(predicate).collect(Collectors.toList()); } }

我們只定義了一個conditionFilter方法,stream()會將當前list作為源創建一個Stream對象,collect(Collectors.toList())是將最終的結果封裝在ArrayList中(這部分會在后續stream學習中詳細介紹,這里只關注filter即可),filter方法接收一個Predicate類型參數用於對目標集合進行過濾。里面並沒有任何具體的邏輯,提供了一種更高層次的抽象化,我們可以把要處理的數據和具體的邏輯通過參數傳遞給conditionFilter即可。理解了這種設計思想后,再看上面的例子就很容易理解,本身邏輯並不復雜,分別取出小於5、大於等於5、小於8的元素,最后一個總是返回true的條件意味着打印出集合中所有元素。
除此之外,Predicate還新增了接口的默認(default)方法和(static)靜態方法。在Java 8以前,接口里的方法要求全部是抽象方法。但是靜態(static)方法只能通過接口名調用,不可以通過實現類的類名或者實現類的對象調用;默認(default)方法只能通過接口實現類的對象來調用。

default Predicate<T> and(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) && other.test(t); } default Predicate<T> or(Predicate<? super T> other) { Objects.requireNonNull(other); return (t) -> test(t) || other.test(t); } default Predicate<T> negate() { return (t) -> !test(t); } static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); }

and方法接收一個Predicate類型,也就是將傳入的條件和當前條件以並且的關系過濾數據。or方法同樣接收一個Predicate類型,將傳入的條件和當前的條件以或者的關系過濾數據。negate就是將當前條件取反。看下具體使用方式

public List<Integer> conditionFilterNegate(List<Integer> list, Predicate<Integer> predicate){ return list.stream().filter(predicate.negate()).collect(Collectors.toList()); } public List<Integer> conditionFilterAnd(List<Integer> list, Predicate<Integer> predicate,Predicate<Integer> predicate2){ return list.stream().filter(predicate.and(predicate2)).collect(Collectors.toList()); } public List<Integer> conditionFilterOr(List<Integer> list, Predicate<Integer> predicate,Predicate<Integer> predicate2){ return list.stream().filter(predicate.or(predicate2)).collect(Collectors.toList()); } //大於5並且是偶數
result = predicateTest.conditionFilterAnd(list, integer -> integer > 5, integer1 -> integer1 % 2 == 0); result.forEach(System.out::println);//6 8 10
System.out.println("-------"); //大於5或者是偶數
result = predicateTest.conditionFilterOr(list, integer -> integer > 5, integer1 -> integer1 % 2 == 0); result.forEach(System.out::println);//2 4 6 8 9 10
System.out.println("-------"); //條件取反
result = predicateTest.conditionFilterNegate(list,integer2 -> integer2 > 5); result.forEach(System.out::println);// 1 2 3 4 5
System.out.println("-------");

我們分別借助Predicate的三個默認方法定義了conditionFilterAnd、conditionFilterOr和conditionFilterNegate方法。然后再下方調用這三個方法,根據傳入的判斷條件觀察輸出結果。

最后再來看一下Predicate接口中的唯一一個靜態方法,Java8中接口中除了增加了默認方法也可以定義靜態方法。

/** * 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); }

isEqual方法返回類型也是Predicate,也就是說通過isEqual方法得到的也是一個用來進行條件判斷的函數式接口實例。而返回的這個函數式接口實例是通過傳入的targetRef的equals方法進行判斷的。我們看一下具體用法

System.out.println(Predicate.isEqual("test").test("test"));//true

這里會用第一個"test"的equals方法判斷與第二個"test"是否相等,結果true。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM