java - 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。
解决方案
受@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);
推荐阅读
- java - 为什么这加起来是 11 而不是 8?
- nginx - Nginx access_log 的路径可以带变量吗?
- sql - 如何存储不带引号的是或否的布尔值?
- ruby-on-rails - 如何显示我的 Rails Web 应用程序的未捆绑的单个 javascript 和 css
- reactjs - 多张图片一张一张上传,带有预览的删除和更改选项
- mysql - 将 mysql 查询抱怨为单个查询
- javascript - Javascript中对象过滤的变异问题
- java - 如何从 Java 中的 JSON 中提取 JSONArray 和 JSONObject
- javascript - 使用递归按顺序生成二进制字符串
- ngx-bootstrap - bs-sortable selection on perticular item 在拖动时选择完整的网格