如何使用Java Stream按属性从对象列表中收集重复对象
按osName筛选重复Computer对象的最优Stream实现方案
核心思路
因为原Computer类未重写hashCode()和equals(),我们完全基于osName属性处理:先统计每个操作系统名称的出现次数,再筛选出所有属于出现次数>1的操作系统的对象。这个方案仅需两次线性遍历,时间复杂度为O(n),是效率最高的实现方式。
分步实现代码
- 将所有Computer实例存入List:
List<Computer> computers = Arrays.asList(c1, c2, c3, c4, c5);
- 统计每个osName的出现次数:
Map<String, Long> osCountMap = computers.stream() .collect(Collectors.groupingBy(Computer::getOsName, Collectors.counting()));
- 过滤出osName重复的对象:
List<Computer> duplicateOsComputers = computers.stream() .filter(comp -> osCountMap.get(comp.getOsName()) > 1) .collect(Collectors.toList());
完整可运行示例
import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Collectors; class Computer { int id; String osName; public Computer(int id, String osName) { this.id = id; this.osName = osName; } // 必须的getter方法 public String getOsName() { return osName; } // 重写toString方便输出查看 @Override public String toString() { return "Computer(" + id + ", \"" + osName + "\")"; } } public class DuplicateComputerFinder { public static void main(String[] args) { Computer c1 = new Computer(1, "Window10"); Computer c2 = new Computer(2, "Window11"); Computer c3 = new Computer(3, "Linux"); Computer c4 = new Computer(4, "Window10"); Computer c5 = new Computer(5, "Window10"); List<Computer> computers = Arrays.asList(c1, c2, c3, c4, c5); // 统计osName出现次数 Map<String, Long> osCountMap = computers.stream() .collect(Collectors.groupingBy(Computer::getOsName, Collectors.counting())); // 筛选重复osName的对象 List<Computer> duplicates = computers.stream() .filter(comp -> osCountMap.get(comp.getOsName()) > 1) .collect(Collectors.toList()); // 打印结果 duplicates.forEach(System.out::println); } }
运行结果
Computer(1, "Window10") Computer(4, "Window10") Computer(5, "Window10")
方案优势
- 高效:仅两次线性遍历,避免了嵌套遍历的O(n²)复杂度
- 无侵入:不需要修改原
Computer类的任何代码 - 易维护:逻辑清晰,每一步职责明确
内容的提问来源于stack exchange,提问作者mRaza
相关产品推荐
相关产品推荐

