如何简化Java 8 Stream API实现Integer列表与自定义对象列表差异查询
问题
输入ID列表:
List<Integer> idList = List.of(100, 101, 102, 103, 104);
从数据库获取的自定义对象列表:
@Getter @Builder public class CustomObject { private int id; } List<CustomObject> fromDB = List.of( CustomObject.builder().id(102).build(), CustomObject.builder().id(104).build() );
需求:找出输入ID列表中未出现在数据库返回的CustomObject列表中的ID。
当前实现代码:
List<Integer> listOfID = fromDB.stream().map(CustomObject::getId).toList(); String list = idList.stream() .filter(element -> !listOfID.contains(element)) .map(String::valueOf) .collect(Collectors.joining(", ")); System.out.println("RESULT: " + list); // 输出结果:100, 101, 103
本人对Stream API经验不足,请问能否简化上述实现?
简化实现方案
可以简化代码,同时还能提升查询性能(原代码用List.contains是O(n)时间复杂度,换成HashSet后是O(1)),有两种实现方式:
方式一:兼顾可读性与性能
// 先将数据库返回的ID存入HashSet Set<Integer> dbIdSet = fromDB.stream() .map(CustomObject::getId) .collect(Collectors.toSet()); // 直接过滤并拼接结果 String result = idList.stream() .filter(id -> !dbIdSet.contains(id)) .map(String::valueOf) .collect(Collectors.joining(", ")); System.out.println("RESULT: " + result);
方式二:追求极致简洁(单流式操作)
String result = idList.stream() .filter(id -> !fromDB.stream() .map(CustomObject::getId) .collect(Collectors.toSet()) .contains(id)) .map(String::valueOf) .collect(Collectors.joining(", ")); System.out.println("RESULT: " + result);
说明
- 用
HashSet存储数据库ID,大幅提升contains操作的效率,数据量越大优势越明显 - 方式一将集合创建与过滤逻辑分离,可读性更强;方式二合并为单流式调用,代码更紧凑
- 两种方式都去掉了原代码中不必要的
List类型中间变量,改用更适合查询场景的Set
内容的提问来源于stack exchange,提问作者Roman Chumak
相关产品推荐
相关产品推荐

