我认为创建这种类型的谓词没有充分的理由,因为它会使您的谓词复杂化。但是,我想到了至少 3 种不同的方式来“改变”谓词状态。
v0 - 只需使用java.util.function.Predicate<T>
final Predicate<String> p1 = "foo"::equals;
final Predicate<String> unit1 = p1.or("bar"::equals);
Assertions.assertTrue(unit1.test("foo"));
Assertions.assertTrue(unit1.test("bar"));
Assertions.assertFalse(unit1.test("baz"));
final Predicate<String> unit2 = p1.or("baz"::equals);
Assertions.assertTrue(unit2.test("foo"));
Assertions.assertTrue(unit2.test("baz"));
这段代码没有任何问题,我仍然会使用它不实现任何自定义类。
v1 - 在自定义谓词实现中“强制转换”
这仍然需要覆盖 Predicate<T> 接口中的所有默认方法,以免在未来的 Java 版本中中断。
public abstract class V1MutablePredicate<T, P extends V1MutablePredicate<T, P>>
implements Predicate<T> {
@Nullable
private final Predicate<T> predicate;
protected V1MutablePredicate(@Nullable final Predicate<T> predicate) {
this.predicate = predicate;
}
protected abstract boolean doTest(T t);
@Nonnull
protected abstract P wrap(@Nonnull Predicate<T> predicate);
@Override
public final boolean test(final T t) {
return predicate == null ? doTest(t) : predicate.test(t);
}
@Nonnull
@Override
public final P and(@Nonnull final Predicate<? super T> other) {
return wrap(Predicate.super.and(other));
}
@Nonnull
@Override
public final P negate() {
return wrap(Predicate.super.negate());
}
@Nonnull
@Override
public final P or(@Nonnull final Predicate<? super T> other) {
return wrap(Predicate.super.or(other));
}
}
private static final class Custom
extends V1MutablePredicate<String, Custom> {
private String s;
Custom(final String s) {
this(null, s);
}
private Custom(@Nullable final Predicate<String> predicate, final String s) {
super(predicate);
this.s = s;
}
@Override
protected boolean doTest(final String t) {
return t.equals(s);
}
@Nonnull
@Override
protected Custom wrap(@Nonnull final Predicate<String> predicate) {
return new Custom(predicate, s);
}
}
@Test
public void test() {
final Custom p1 = new Custom("foo");
final Custom p2 = new Custom("bar");
final Custom unit = p1.or(p2);
Assertions.assertTrue(unit.test("foo"));
Assertions.assertTrue(unit.test("bar"));
Assertions.assertFalse(unit.test("baz"));
p2.s = "baz";
Assertions.assertTrue(unit.test("foo"));
Assertions.assertTrue(unit.test("baz"));
}
这似乎最接近您想要完成的目标。
v2 - 从外部注入谓词状态
public final class V2MutablePredicate<T, S>
implements Predicate<T> {
private final Supplier<? extends S> stateSupplier;
private final BiPredicate<? super S, ? super T> predicate;
public V2MutablePredicate(final Supplier<? extends S> stateSupplier, final BiPredicate<? super S, ? super T> predicate) {
this.stateSupplier = stateSupplier;
this.predicate = predicate;
}
@Override
public boolean test(final T t) {
return predicate.test(stateSupplier.get(), t);
}
}
final AtomicReference<String> r1 = new AtomicReference<>("foo");
final V2MutablePredicate<String, String> p1 = new V2MutablePredicate<>(r1::get, String::equals);
final AtomicReference<String> r2 = new AtomicReference<>("bar");
final V2MutablePredicate<String, String> p2 = new V2MutablePredicate<>(r2::get, String::equals);
final Predicate<String> unit = p1.or(p2);
Assertions.assertTrue(unit.test("foo"));
Assertions.assertTrue(unit.test("bar"));
Assertions.assertFalse(unit.test("baz"));
r2.set("baz");
Assertions.assertTrue(unit.test("foo"));
Assertions.assertTrue(unit.test("baz"));
此实现需要从管理多个要处理的对象的外部更改状态,并且还需要“状态”类,但它不需要覆盖默认方法,并且还需要供应商在每个对象中提供值test方法调用。