如何用Java 8 Streams API筛选含重复姓名的Person对象子列表?
用Java 8 Streams API筛选重复姓名的Person实例
这个需求很常见,而且完全不需要提前知道列表里的姓名取值,我们可以分两步走:先找出所有重复的姓名,再用这些姓名过滤原列表。直接上完整实现,再拆解细节:
完整代码实现
import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; import java.util.stream.Collectors; class Person { public String name; public int age; public Person(String name, int age) { this.name = name; this.age = age; } @Override public String toString() { return name + ": " + age; } // 建议添加getter方法,比直接访问public字段更规范 public String getName() { return name; } } public class DuplicatePersonFilter { public static void main(String[] args) { List<Person> personsList = new ArrayList<>(); personsList.add(new Person("John", 28)); personsList.add(new Person("Paul", 29)); personsList.add(new Person("Adam", 30)); personsList.add(new Person("Peter", 31)); personsList.add(new Person("Kate", 32)); personsList.add(new Person("John", 67)); personsList.add(new Person("Paul", 68)); personsList.add(new Person("Adam", 69)); // 1. 统计每个姓名的出现次数 Map<String, Long> nameCountMap = personsList.stream() .collect(Collectors.groupingBy(Person::getName, Collectors.counting())); // 2. 筛选出出现次数>1的姓名,存入Set Set<String> duplicateNames = nameCountMap.entrySet().stream() .filter(entry -> entry.getValue() > 1) .map(Map.Entry::getKey) .collect(Collectors.toSet()); // 3. 过滤原列表,保留姓名在duplicateNames中的Person List<Person> result = personsList.stream() .filter(person -> duplicateNames.contains(person.getName())) .collect(Collectors.toList()); // 打印结果 result.forEach(System.out::println); } }
代码拆解说明
统计姓名出现次数:
用Collectors.groupingBy按姓名对Person对象分组,搭配Collectors.counting()统计每组的元素数量,得到一个Map<String, Long>——key是姓名,value是该姓名出现的次数。获取重复姓名集合:
遍历第一步的Map,过滤出value(次数)大于1的entry,提取对应的key(姓名)并收集成Set。用Set是因为它的contains查询效率比List高,后续过滤原列表时会更高效。过滤原列表:
再次遍历原Person列表,只要当前Person的姓名存在于重复姓名Set中,就保留该对象,最后收集成结果列表。
运行结果
执行代码后,控制台会输出:
John: 28 John: 67 Paul: 29 Paul: 68 Adam: 30 Adam: 69
完全符合你的需求。
内容的提问来源于stack exchange,提问作者Ravi
相关产品推荐
相关产品推荐

