如何在Java中用Stream获取两个Person列表中男性的对称差集?
问题描述
我定义了如下Java类:
public class Person { private String name; private String gender; }
我拥有两个Person列表:
列表A:
index 0: name: "Mike", gender: "male" index 1: name: "Jane", gender: "female" index 2: name: "Ellen", gender: "female" index 3: name: "Ben", gender: "male" index 4: name: "Jimmy", gender: "male" index 5: name: "Maria", gender: "female"
列表B:
index 0: name: "Ben", gender: "male" index 1: name: "Maria", gender: "female" index 2: name: "Jane", gender: "female" index 3: name: "Brian", gender: "male" index 4: name: "Sofia", gender: "female" index 5: name: "John", gender: "male" index 6: name: "Jimmy", gender: "male"
我希望生成一个新列表,包含所有仅存在于其中一个列表中的男性,即既包含列表A中有但列表B中没有的男性,也包含列表B中有但列表A中没有的男性。我尝试用Stream实现,但尚未找到方法。
解决方案
要实现这个需求,我们可以通过Java Stream分步骤处理:
步骤说明
- 过滤男性数据:先从两个列表中筛选出男性,减少后续处理的无效数据。
- 提取姓名集合:将两个列表中男性的姓名存入
Set,利用Set的快速查询特性判断存在性(假设姓名是Person的唯一标识)。 - 计算对称差集:分别找出仅在A中存在的男性、仅在B中存在的男性,最后合并两部分结果。
完整代码实现
首先给Person类补充必要的getter、构造方法以及equals/hashCode(保证集合操作的正确性):
import java.util.Objects; public class Person { private String name; private String gender; public Person(String name, String gender) { this.name = name; this.gender = gender; } public String getName() { return name; } public String getGender() { return gender; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return Objects.equals(name, person.name) && Objects.equals(gender, person.gender); } @Override public int hashCode() { return Objects.hash(name, gender); } @Override public String toString() { return "Person{name='" + name + "', gender='" + gender + "'}"; } }
然后是核心逻辑代码:
import java.util.List; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; public class Main { public static void main(String[] args) { // 初始化列表A List<Person> listA = List.of( new Person("Mike", "male"), new Person("Jane", "female"), new Person("Ellen", "female"), new Person("Ben", "male"), new Person("Jimmy", "male"), new Person("Maria", "female") ); // 初始化列表B List<Person> listB = List.of( new Person("Ben", "male"), new Person("Maria", "female"), new Person("Jane", "female"), new Person("Brian", "male"), new Person("Sofia", "female"), new Person("John", "male"), new Person("Jimmy", "male") ); // 提取列表A的男性姓名集合 Set<String> maleNamesA = listA.stream() .filter(p -> "male".equals(p.getGender())) .map(Person::getName) .collect(Collectors.toSet()); // 提取列表B的男性姓名集合 Set<String> maleNamesB = listB.stream() .filter(p -> "male".equals(p.getGender())) .map(Person::getName) .collect(Collectors.toSet()); // 获取仅在A中存在的男性 List<Person> onlyInA = listA.stream() .filter(p -> "male".equals(p.getGender())) .filter(p -> !maleNamesB.contains(p.getName())) .collect(Collectors.toList()); // 获取仅在B中存在的男性 List<Person> onlyInB = listB.stream() .filter(p -> "male".equals(p.getGender())) .filter(p -> !maleNamesA.contains(p.getName())) .collect(Collectors.toList()); // 合并结果 List<Person> result = Stream.concat(onlyInA.stream(), onlyInB.stream()) .collect(Collectors.toList()); // 输出结果 result.forEach(System.out::println); } }
运行结果
执行后会输出:
Person{name='Mike', gender='male'} Person{name='Brian', gender='male'} Person{name='John', gender='male'}
内容的提问来源于stack exchange,提问作者TheStranger
相关产品推荐
相关产品推荐

