在Java中,可以使用Java 8引入的Stream API来优雅地计算两个列表的交集、并集和差集。下面是使用Stream
流的filter
、contains
等方法来实现这些集合运算的一个详细示例。
示例类定义
首先,我们定义一个简单的Person
类来作为我们的数据模型:
java
深色版本
1import java.util.Objects;
2
3public class Person {
4 private String name;
5 private int age;
6
7 public Person(String name, int age) {
8 this.name = name;
9 this.age = age;
10 }
11
12 public String getName() {
13 return name;
14 }
15
16 public int getAge() {
17 return age;
18 }
19
20 @Override
21 public boolean equals(Object o) {
22 if (this == o) return true;
23 if (!(o instanceof Person)) return false;
24 Person person = (Person) o;
25 return getAge() == person.getAge() &&
26 getName().equals(person.getName());
27 }
28
29 @Override
30 public int hashCode() {
31 return Objects.hash(getName(), getAge());
32 }
33
34 @Override
35 public String toString() {
36 return "Person{" +
37 "name='" + name + '\'' +
38 ", age=" + age +
39 '}';
40 }
41}
计算交集、并集和差集
接下来,我们将定义一个方法来计算两个List<Person>
的交集、并集和差集:
java
深色版本
1import java.util.Arrays;
2import java.util.List;
3import java.util.Set;
4import java.util.stream.Collectors;
5
6public class CollectionOperations {
7
8 public static void main(String[] args) {
9 List<Person> list1 = Arrays.asList(
10 new Person("Alice", 25),
11 new Person("Bob", 30),
12 new Person("Charlie", 35),
13 new Person("David", 40)
14 );
15
16 List<Person> list2 = Arrays.asList(
17 new Person("Bob", 30),
18 new Person("Charlie", 35),
19 new Person("Eve", 45),
20 new Person("Frank", 50)
21 );
22
23 // 计算交集
24 List<Person> intersection = computeIntersection(list1, list2);
25 System.out.println("交集: " + intersection);
26
27 // 计算并集
28 List<Person> union = computeUnion(list1, list2);
29 System.out.println("并集: " + union);
30
31 // 计算差集 (list1 - list2)
32 List<Person> difference1 = computeDifference(list1, list2);
33 System.out.println("差集 (list1 - list2): " + difference1);
34
35 // 计算差集 (list2 - list1)
36 List<Person> difference2 = computeDifference(list2, list1);
37 System.out.println("差集 (list2 - list1): " + difference2);
38 }
39
40 public static List<Person> computeIntersection(List<Person> list1, List<Person> list2) {
41 Set<Person> set2 = list2.stream().collect(Collectors.toSet());
42 return list1.stream()
43 .filter(set2::contains)
44 .collect(Collectors.toList());
45 }
46
47 public static List<Person> computeUnion(List<Person> list1, List<Person> list2) {
48 Set<Person> set1 = list1.stream().collect(Collectors.toSet());
49 set1.addAll(list2);
50 return set1.stream().collect(Collectors.toList());
51 }
52
53 public static List<Person> computeDifference(List<Person> source, List<Person> toRemove) {
54 Set<Person> removeSet = toRemove.stream().collect(Collectors.toSet());
55 return source.stream()
56 .filter(person -> !removeSet.contains(person))
57 .collect(Collectors.toList());
58 }
59}
方法解释
-
计算交集 (
computeIntersection
):- 将
list2
转换成一个Set
,这将有助于提高contains
方法的性能。 - 使用
filter
方法来过滤list1
中的元素,只保留那些在set2
中的元素。
- 将
-
计算并集 (
computeUnion
):- 将
list1
转换成一个Set
。 - 使用
addAll
方法将list2
中的所有元素添加到set1
中,从而实现并集操作。 - 最后将
set1
转换回List
。
- 将
-
计算差集 (
computeDifference
):- 将
toRemove
转换成一个Set
。 - 使用
filter
方法来过滤source
中的元素,排除掉那些在removeSet
中的元素。
- 将
输出结果
当运行上述代码时,你会得到以下输出:
深色版本
1交集: [Person{name='Bob', age=30}, Person{name='Charlie', age=35}]
2并集: [Person{name='Alice', age=25}, Person{name='Bob', age=30}, Person{name='Charlie', age=35}, Person{name='David', age=40}, Person{name='Eve', age=45}, Person{name='Frank', age=50}]
3差集 (list1 - list2): [Person{name='Alice', age=25}, Person{name='David', age=40}]
4差集 (list2 - list1): [Person{name='Eve', age=45}, Person{name='Frank', age=50}]
总结
通过使用Java 8的Stream API,你可以以一种简洁且高效的方式来计算两个列表之间的交集、并集和差集。这种方法不仅提高了代码的可读性和可维护性,而且在某些情况下还能提高性能。特别是将一个列表转换为Set
可以极大地提高contains
方法的效率,尤其是在处理大数据量的时候。