首页 > 解决方案 > Java 流过滤 - 使用 Predicate而不是谓词, 直接对类的一个字段进行操作

问题描述

使用java流,我有一个ClassA列表,应用于过滤流,所以list.stream().filter(predicate).etc。这样,谓词将需要 ClassA 的谓词才能应用,但我真的想要 String 的谓词,因为 ClassA.Field1 是 String 类型。所以与其让谓词包含 f -> f.getField1().equals("foo"),我希望它是 f -> f.equals("foo"),直接在字段上操作。原因是因为我也有ClassB、ClassC、predicateA、predicateB、predicateC。我不想使用多个谓词,我想使用一个谓词,因为它们的操作都是相同的,检查字符串是否具有预期的内容。

这个缺少什么链接,我需要如何转换流来做到这一点?

对于其他上下文,过滤后我需要从过滤列表中提取第二个字段,因此目标是拥有 ClassA.Field2.val (例如,我需要提取与该项目名称相关联的项目 ID,所以我按名称过滤)

另外:这是一个简化,实际需要是使用startsWith,而不是equals。

标签: javajava-8java-stream

解决方案


受@bedrin 帖子的启发,这里有一种不需要新课程的方法

假设您有以下课程:

class ClassA {
    String name;
    //getter, setter ..
}

class ClassB {
    String name;
    //getter, setter ..
}

和列表,例如:

List<ClassA> myAs = List.of(new ClassA("myA_1"), new ClassA("myA_1"), new ClassA("myA_42"));
List<ClassB> myBs = List.of(new ClassB("myB_1"), new ClassB("myB_9"), new ClassB("myB_33"));

然后你可以编写一个方法来接受一个字段提取函数和你想要测试的字符串:

private static <T> Predicate<T> nameEquals( Function<? super T, ?> fieldExtractor, String toTestAgainst ) {
    return t -> toTestAgainst.equals(fieldExtractor.apply(t));
}

并使用上述方法过滤您的列表。示例用法:

myAs.stream().filter(nameEquals(ClassA::getName, "myA_1")).forEach(System.out::println);
myBs.stream().filter(nameEquals(ClassB::getName, "myB_1")).forEach(System.out::println);

推荐阅读