Почему бы вам не определить несколько предикатов для каждого подтипа, добавить эти предикаты в список и, наконец, создать предикат, выполнив or
всех предикатов в списке.
public static Predicate<Foo> anotherIsFoo() {
return predicates.stream()
.reduce(foo -> false, (a, b) -> a.or(b));
}
В приведенном выше коде предполагается, что predicates
- это список, содержащий все предикаты для каждого подтипа.
Полный код выглядит так:
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
class Foo {}
class Boo extends Foo {}
class Goo extends Foo {}
public class Predicates {
public static List<Predicate<Foo>> predicates = List.of(isGoo(), isFoo());
public static Predicate<Foo> isGoo() {
return foo -> foo instanceof Goo;
}
public static Predicate<Foo> isBoo() {
return goo -> goo instanceof Boo;
}
public static Predicate<Foo> anotherIsFoo() {
return predicates.stream()
.reduce(foo -> false, (a, b) -> a.or(b));
}
public static Predicate<Foo> isFoo() {
return foo -> foo instanceof Foo;
}
public static void main(String[] args) {
List<Foo> list = List.of(new Boo(), new Goo(), new Goo(), new Goo());
List<Boo> boos = list.stream()
.filter(Predicates.isBoo())
.map(boo -> (Boo) boo)
.collect(Collectors.toList());
System.out.println(boos.size()); // 1
List<Goo> goos = list.stream()
.filter(Predicates.isGoo())
.map(goo -> (Goo) goo)
.collect(Collectors.toList());
System.out.println(goos.size()); //3
List<Foo> foos = list.stream()
.filter(Predicates.isFoo())
.collect(Collectors.toList());
System.out.println(foos.size()); // 4
List<Foo> foos1 = list.stream()
.filter(Predicates.anotherIsFoo())
.collect(Collectors.toList());
System.out.println(foos1.size()); // 4
}
}
Приведенный выше код отвечает на ваш запрос: «У меня не может быть двух разных типов в одном списке, даже если они наследуются от одного и того же суперкласса!»
Для приведенного выше кода требуется Java 9 или выше.