探索Java8:(三)Predicate接口的使用
阿新 • • 發佈:2018-10-11
objects 符號 boolean 我只 需要 collect 接下來 操作 interface
上一篇學習了下Function接口的使用,本篇我們學習下另一個實用的函數式接口Predicate。
Predicate的源碼跟Function的很像,我們可以對比這兩個來分析下。直接上Predicate的源碼:
public interface Predicate<T> { /** * Evaluates this predicate on the given argument. */ 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. */ 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. */ 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. */ 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)}. */ static <T> Predicate<T> isEqual(Object targetRef) { return (null == targetRef) ? Objects::isNull : object -> targetRef.equals(object); } }
Predicate是個斷言式接口其參數是<T,boolean>,也就是給一個參數T,返回boolean類型的結果。跟Function一樣,Predicate的具體實現也是根據傳入的lambda表達式來決定的。
boolean test(T t);
接下來我們看看Predicate默認實現的三個重要方法and,or和negate
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); }
這三個方法對應了java的三個連接符號&&、||和!,基本的使用十分簡單,我們給一個例子看看:
int[] numbers= {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; List<Integer> list=new ArrayList<>(); for(int i:numbers) { list.add(i); } Predicate<Integer> p1=i->i>5; Predicate<Integer> p2=i->i<20; Predicate<Integer> p3=i->i%2==0; List test=list.stream().filter(p1.and(p2).and(p3)).collect(Collectors.toList()); System.out.println(test.toString()); /** print:[6, 8, 10, 12, 14]*/
我們定義了三個斷言p1,p2,p3。現在有一個從1~15的list,我們需要過濾這個list。上述的filter是過濾出所有大於5小於20,並且是偶數的列表。
假如突然我們的需求變了,我們現在需要過濾出奇數。那麽我不可能直接去改Predicate,因為實際項目中這個條件可能在別的地方也要使用。那麽此時我只需要更改filter中Predicate的條件。
List test=list.stream().filter(p1.and(p2).and(p3.negate())).collect(Collectors.toList());
/** print:[7, 9, 11, 13, 15]*/
我們直接對p3這個條件取反就可以實現了。是不是很簡單?
isEqual這個方法的返回類型也是Predicate,所以我們也可以把它作為函數式接口進行使用。我們可以當做==操作符來使用。
List test=list.stream()
.filter(p1.and(p2).and(p3.negate()).and(Predicate.isEqual(7)))
.collect(Collectors.toList());
/** print:[7] */
探索Java8:(三)Predicate接口的使用