用泛型和继承来谓词 java 8



我有三个Foo Boo Goo对象,其中包含Foo超类的Boo和Goo子类型。

我正在使用谓词来过滤列表,如下所示

public class Predicates {
        public static Predicate<Foo> isBoo() {
            foo ->  { 
                  Boo boo = (Boo) foo; 
                  return boo.isBoo();
             };
         }
    public static Predicate<Goo> isGoo() {
            foo ->  { 
                  Goo goo = (Goo) foo; 
                  return goo.isGoo();
             };
     }
}

我接下来要实现的是指定泛型类型而不是编译时类型。

public class Predicates {
        public static <T extends Foo> Predicate<T> isBoo() {
            foo ->  { 
                  // check both with instanceof
             };
         }
    public static <T extends Foo> Predicate<T> isGoo() {
            foo ->  { 
                  Goo goo = (Goo) foo; 
                  return boo.isGoo();
             };
     }
    public static <T extends Foo> Predicate<T> isFoo() {
            isGoo().or(isBoo());
     }
}

当将多个谓词与 OR 或 AND 组合在一起时,似乎不可能将泛型与谓词一起使用。 知道谓词可能有不同的类型,但仍然扩展了超类。

需要光!

为什么不为每个子类型定义多个谓词,将这些谓词添加到列表中,最后通过对列表中的所有谓词进行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 或更高版本。

最新更新