Я немного опоздал с решением, в любом случае я оставлю его здесь.
У меня была идея написать конструктор для построения комплекса Predicate
, но в итоге я получил класс FilterCondition
и метод FilterCondition.combine
.
Stream.of("123", "1", "12345", "", "12", "", "2")
.filter(FilterCondition.<String>combine(
FilterCondition.of(() -> true, s -> s.contains("3")),
FilterCondition.of(() -> true, s -> s.contains("2")),
FilterCondition.of(() -> false, s -> s.isEmpty())
).toPredicate())
.collect(Collectors.toList());
При статическом импорте FilterCondition.of
и FilterCondition.combine,
это выглядело бы еще лучше.
Stream.of("123", "1", "12345", "", "12", "", "2")
.filter(combine(
of(() -> true, s -> s.contains("3")),
of(() -> true, s -> s.contains("2")),
of(() -> false, String::isEmpty)
).toPredicate())
.collect(Collectors.toList());
FilterCondition<T>
- это, по сути, Predicate<T>
с дополнительным условием проверки необходимости применения predicate
.
FilterCondition.combine
занимает около FilterCondition
с и составляет комбинированное.
class FilterCondition<T> {
private final Supplier<Boolean> filterEnabled;
private final Predicate<T> predicate;
private FilterCondition(Supplier<Boolean> filterEnabled, Predicate<T> predicate) {
this.filterEnabled = filterEnabled;
this.predicate = predicate;
}
public static <T> FilterCondition<T> of(Supplier<Boolean> filterEnabled, Predicate<T> predicate) {
return new FilterCondition<>(filterEnabled, predicate);
}
@SafeVarargs
public static <T> FilterCondition<T> combine(FilterCondition<T>... conditions) {
return new FilterCondition<>(
() -> true,
Arrays.stream(conditions).filter(i -> i.filterEnabled.get()).map(i -> i.predicate).reduce(Predicate::and).orElse(t -> true)
);
}
public Predicate<T> toPredicate() {
return predicate;
}
}