Predicate
斷言,判斷一個對象是否滿足一定條件。
package com.google.common.base;
@FunctionalInterface
@GwtCompatible
public interface Predicate<T> extends java.util.function.Predicate<T> {
@CanIgnoreReturnValue
boolean apply(@Nullable T input);
@Override
boolean equals(@Nullable Object object);
// apply的測試方法
@Override
default boolean test(@Nullable T input) {
return apply(input);
}
}
Predicates類,Predicate接口的指南類,實現了Predicate接口並且添加了一些常用的靜態方法,主要關注apply方法。
package com.google.common.base;
@GwtCompatible(emulated = true)
public final class Predicates {
private Predicates() {}
// TODO(kevinb): considering having these implement a VisitablePredicate
// interface which specifies an accept(PredicateVisitor) method.
/**
* 返回結果爲true的Predicate,ObjectPredicate是一個內部枚舉類
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> alwaysTrue() {
return ObjectPredicate.ALWAYS_TRUE.withNarrowedType();
}
/**
* 返回結果爲false的Predicate
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> alwaysFalse() {
return ObjectPredicate.ALWAYS_FALSE.withNarrowedType();
}
/**
* 返回判斷對象是否爲null的Predicate
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> isNull() {
return ObjectPredicate.IS_NULL.withNarrowedType();
}
/**
* 返回判斷對象是否不爲null的Predicate
*/
@GwtCompatible(serializable = true)
public static <T> Predicate<T> notNull() {
return ObjectPredicate.NOT_NULL.withNarrowedType();
}
/**
* 返回與傳入predicate結果相反的predicate,NotPredicate爲內部Predicate實現類
*/
public static <T> Predicate<T> not(Predicate<T> predicate) {
return new NotPredicate<T>(predicate);
}
/**
* 返回傳入的predicate list集合所有結果與操作之後的predicate,AndPredicate爲內部Predicate實現類
*/
public static <T> Predicate<T> and(Iterable<? extends Predicate<? super T>> components) {
return new AndPredicate<T>(defensiveCopy(components));
}
/**
* and重載方法,參數爲predicate可變參數
*/
@SafeVarargs
public static <T> Predicate<T> and(Predicate<? super T>... components) {
// 將多個predicate整理成一個列表,defensiveCopy爲淺拷貝
return new AndPredicate<T>(defensiveCopy(components));
}
/**
* 將兩個predicate合併爲一個
*/
public static <T> Predicate<T> and(Predicate<? super T> first, Predicate<? super T> second) {
return new AndPredicate<T>(
Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
* 多個predicate結果並集,OrPredicate爲內部Predicate實現類
*/
public static <T> Predicate<T> or(Iterable<? extends Predicate<? super T>> components) {
// 淺拷貝多個predicate爲一個list
return new OrPredicate<T>(defensiveCopy(components));
}
/**
* 可變參數predicate求並集
*/
@SafeVarargs
public static <T> Predicate<T> or(Predicate<? super T>... components) {
return new OrPredicate<T>(defensiveCopy(components));
}
/**
* 兩個predicate求並集
*/
public static <T> Predicate<T> or(Predicate<? super T> first, Predicate<? super T> second) {
return new OrPredicate<T>(
Predicates.<T>asList(checkNotNull(first), checkNotNull(second)));
}
/**
* 返回一個判斷是否相等的Prediacate
*/
public static <T> Predicate<T> equalTo(@Nullable T target) {
return (target == null) ? Predicates.<T>isNull()
: new IsEqualToPredicate<T>(target);
}
/**
* Object.isInstance方法,以Predicate封裝返回
*/
@GwtIncompatible // Class.isInstance
public static Predicate<Object> instanceOf(Class<?> clazz) {
return new InstanceOfPredicate(clazz);
}
/**
* clazz.isAssignableFrom
*/
@GwtIncompatible // Class.isAssignableFrom
@Beta
@Deprecated
public static Predicate<Class<?>> assignableFrom(Class<?> clazz) {
return subtypeOf(clazz);
}
/**
* clazz.isAssignableFrom
*/
@GwtIncompatible // Class.isAssignableFrom
@Beta
public static Predicate<Class<?>> subtypeOf(Class<?> clazz) {
return new SubtypeOfPredicate(clazz);
}
/**
* 返回一個判斷某個元素是否在target集合內的Predicate
*/
public static <T> Predicate<T> in(Collection<? extends T> target) {
return new InPredicate<T>(target);
}
/**
* 類型轉換
*/
public static <A, B> Predicate<A> compose(
Predicate<B> predicate, Function<A, ? extends B> function) {
return new CompositionPredicate<A, B>(predicate, function);
}
/**
* 使用正則表達式進行字符串匹配
*/
@GwtIncompatible // Only used by other GWT-incompatible code.
public static Predicate<CharSequence> containsPattern(String pattern) {
return new ContainsPatternFromStringPredicate(pattern);
}
/**
* 使用JDK正則表達式進行字符串匹配
*/
@GwtIncompatible(value = "java.util.regex.Pattern")
public static Predicate<CharSequence> contains(Pattern pattern) {
return new ContainsPatternPredicate(new JdkPattern(pattern));
}
// End public API, begin private implementation classes.
// Package private for GWT serialization.
enum ObjectPredicate implements Predicate<Object> {
/** @see Predicates#alwaysTrue() */
ALWAYS_TRUE {
@Override
public boolean apply(@Nullable Object o) {
return true;
}
@Override
public String toString() {
return "Predicates.alwaysTrue()";
}
},
/** @see Predicates#alwaysFalse() */
ALWAYS_FALSE {
@Override
public boolean apply(@Nullable Object o) {
return false;
}
@Override
public String toString() {
return "Predicates.alwaysFalse()";
}
},
/** @see Predicates#isNull() */
IS_NULL {
@Override
public boolean apply(@Nullable Object o) {
return o == null;
}
@Override
public String toString() {
return "Predicates.isNull()";
}
},
/** @see Predicates#notNull() */
NOT_NULL {
@Override
public boolean apply(@Nullable Object o) {
return o != null;
}
@Override
public String toString() {
return "Predicates.notNull()";
}
};
@SuppressWarnings("unchecked") // safe contravariant cast
<T> Predicate<T> withNarrowedType() {
return (Predicate<T>) this;
}
}
/** @see Predicates#not(Predicate) */
private static class NotPredicate<T> implements Predicate<T>, Serializable {
final Predicate<T> predicate;
NotPredicate(Predicate<T> predicate) {
this.predicate = checkNotNull(predicate);
}
@Override
public boolean apply(@Nullable T t) {
return !predicate.apply(t);
}
@Override
public int hashCode() {
return ~predicate.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof NotPredicate) {
NotPredicate<?> that = (NotPredicate<?>) obj;
return predicate.equals(that.predicate);
}
return false;
}
@Override
public String toString() {
return "Predicates.not(" + predicate + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#and(Iterable) */
private static class AndPredicate<T> implements Predicate<T>, Serializable {
private final List<? extends Predicate<? super T>> components;
private AndPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
for (int i = 0; i < components.size(); i++) {
if (!components.get(i).apply(t)) {
return false;
}
}
return true;
}
@Override
public int hashCode() {
// add a random number to avoid collisions with OrPredicate
return components.hashCode() + 0x12472c2c;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof AndPredicate) {
AndPredicate<?> that = (AndPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
@Override
public String toString() {
return toStringHelper("and", components);
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#or(Iterable) */
private static class OrPredicate<T> implements Predicate<T>, Serializable {
private final List<? extends Predicate<? super T>> components;
private OrPredicate(List<? extends Predicate<? super T>> components) {
this.components = components;
}
@Override
public boolean apply(@Nullable T t) {
// Avoid using the Iterator to avoid generating garbage (issue 820).
for (int i = 0; i < components.size(); i++) {
if (components.get(i).apply(t)) {
return true;
}
}
return false;
}
@Override
public int hashCode() {
// add a random number to avoid collisions with AndPredicate
return components.hashCode() + 0x053c91cf;
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof OrPredicate) {
OrPredicate<?> that = (OrPredicate<?>) obj;
return components.equals(that.components);
}
return false;
}
@Override
public String toString() {
return toStringHelper("or", components);
}
private static final long serialVersionUID = 0;
}
private static String toStringHelper(String methodName, Iterable<?> components) {
StringBuilder builder =
new StringBuilder("Predicates.").append(methodName).append('(');
boolean first = true;
for (Object o : components) {
if (!first) {
builder.append(',');
}
builder.append(o);
first = false;
}
return builder.append(')').toString();
}
/** @see Predicates#equalTo(Object) */
private static class IsEqualToPredicate<T> implements Predicate<T>, Serializable {
private final T target;
private IsEqualToPredicate(T target) {
this.target = target;
}
@Override
public boolean apply(T t) {
return target.equals(t);
}
@Override
public int hashCode() {
return target.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof IsEqualToPredicate) {
IsEqualToPredicate<?> that = (IsEqualToPredicate<?>) obj;
return target.equals(that.target);
}
return false;
}
@Override
public String toString() {
return "Predicates.equalTo(" + target + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#instanceOf(Class) */
@GwtIncompatible // Class.isInstance
private static class InstanceOfPredicate implements Predicate<Object>, Serializable {
private final Class<?> clazz;
private InstanceOfPredicate(Class<?> clazz) {
this.clazz = checkNotNull(clazz);
}
@Override
public boolean apply(@Nullable Object o) {
return clazz.isInstance(o);
}
@Override
public int hashCode() {
return clazz.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof InstanceOfPredicate) {
InstanceOfPredicate that = (InstanceOfPredicate) obj;
return clazz == that.clazz;
}
return false;
}
@Override
public String toString() {
return "Predicates.instanceOf(" + clazz.getName() + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#subtypeOf(Class) */
@GwtIncompatible // Class.isAssignableFrom
private static class SubtypeOfPredicate implements Predicate<Class<?>>, Serializable {
private final Class<?> clazz;
private SubtypeOfPredicate(Class<?> clazz) {
this.clazz = checkNotNull(clazz);
}
@Override
public boolean apply(Class<?> input) {
return clazz.isAssignableFrom(input);
}
@Override
public int hashCode() {
return clazz.hashCode();
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof SubtypeOfPredicate) {
SubtypeOfPredicate that = (SubtypeOfPredicate) obj;
return clazz == that.clazz;
}
return false;
}
@Override
public String toString() {
return "Predicates.subtypeOf(" + clazz.getName() + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#in(Collection) */
private static class InPredicate<T> implements Predicate<T>, Serializable {
private final Collection<?> target;
private InPredicate(Collection<?> target) {
this.target = checkNotNull(target);
}
@Override
public boolean apply(@Nullable T t) {
try {
return target.contains(t);
} catch (NullPointerException e) {
return false;
} catch (ClassCastException e) {
return false;
}
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof InPredicate) {
InPredicate<?> that = (InPredicate<?>) obj;
return target.equals(that.target);
}
return false;
}
@Override
public int hashCode() {
return target.hashCode();
}
@Override
public String toString() {
return "Predicates.in(" + target + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#compose(Predicate, Function) */
private static class CompositionPredicate<A, B> implements Predicate<A>, Serializable {
final Predicate<B> p;
final Function<A, ? extends B> f;
private CompositionPredicate(Predicate<B> p, Function<A, ? extends B> f) {
this.p = checkNotNull(p);
this.f = checkNotNull(f);
}
@Override
public boolean apply(@Nullable A a) {
return p.apply(f.apply(a));
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof CompositionPredicate) {
CompositionPredicate<?, ?> that = (CompositionPredicate<?, ?>) obj;
return f.equals(that.f) && p.equals(that.p);
}
return false;
}
@Override
public int hashCode() {
return f.hashCode() ^ p.hashCode();
}
@Override
public String toString() {
// TODO(cpovirk): maybe make this look like the method call does ("Predicates.compose(...)")
return p + "(" + f + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#contains(Pattern) */
@GwtIncompatible // Only used by other GWT-incompatible code.
private static class ContainsPatternPredicate implements Predicate<CharSequence>, Serializable {
final CommonPattern pattern;
ContainsPatternPredicate(CommonPattern pattern) {
this.pattern = checkNotNull(pattern);
}
@Override
public boolean apply(CharSequence t) {
return pattern.matcher(t).find();
}
@Override
public int hashCode() {
// Pattern uses Object.hashCode, so we have to reach
// inside to build a hashCode consistent with equals.
return Objects.hashCode(pattern.pattern(), pattern.flags());
}
@Override
public boolean equals(@Nullable Object obj) {
if (obj instanceof ContainsPatternPredicate) {
ContainsPatternPredicate that = (ContainsPatternPredicate) obj;
// Pattern uses Object (identity) equality, so we have to reach
// inside to compare individual fields.
return Objects.equal(pattern.pattern(), that.pattern.pattern())
&& pattern.flags() == that.pattern.flags();
}
return false;
}
@Override
public String toString() {
String patternString =
MoreObjects.toStringHelper(pattern)
.add("pattern", pattern.pattern())
.add("pattern.flags", pattern.flags())
.toString();
return "Predicates.contains(" + patternString + ")";
}
private static final long serialVersionUID = 0;
}
/** @see Predicates#containsPattern(String) */
@GwtIncompatible // Only used by other GWT-incompatible code.
private static class ContainsPatternFromStringPredicate extends ContainsPatternPredicate {
ContainsPatternFromStringPredicate(String string) {
super(Platform.compilePattern(string));
}
@Override
public String toString() {
return "Predicates.containsPattern(" + pattern.pattern() + ")";
}
private static final long serialVersionUID = 0;
}
private static <T> List<Predicate<? super T>> asList(
Predicate<? super T> first, Predicate<? super T> second) {
// TODO(kevinb): understand why we still get a warning despite @SafeVarargs!
return Arrays.<Predicate<? super T>>asList(first, second);
}
private static <T> List<T> defensiveCopy(T... array) {
return defensiveCopy(Arrays.asList(array));
}
// 引用拷貝,淺拷貝
static <T> List<T> defensiveCopy(Iterable<T> iterable) {
ArrayList<T> list = new ArrayList<T>();
for (T element : iterable) {
list.add(checkNotNull(element));
}
return list;
}
}