如何获得包含两组之间差异的列表?
How can I get a list containing the differences between two sets?
假设我有两套:
Set<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c", "d", "e") );
Set<String> set2 = new HashSet<>(Arrays.asList("b", "c", "d", "e", "f") );
在性能方面比较两者并获得 List
差异的最简单和最好的方法是什么?
这意味着我应该得到一个包含 "a"
和 "f"
的列表。这里棘手的是,差异可能出现在任何一个列表中。
我只能让它与 for 循环一起工作,但必须有更简单的方法...
请按照我发送的屏幕截图进行操作 我认为这是使用 java 8 个流
的最简单方法
是这样的吗?
public static void main(String[] args) {
Set<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c", "d", "e") );
Set<String> set2 = new HashSet<>(Arrays.asList("b", "c", "d", "e", "f") );
//get intersection array
Set<String> listSame = new HashSet<>(set2);
listSame.retainAll(set1);
System.out.println(listSame);
//get union array
Set<String> listDiff = new HashSet<>(set1);
listDiff.addAll(set2);
// get difference
listDiff.removeAll(listSame);
System.out.println(listDiff);
}
最好的方法可能是使用并集和交集,然后求差。
实现此目的的一种方法是创建一组一个集合,遍历另一个集合并在删除元素时检查是否包含该元素:
Collection<String> c1 = Arrays.asList("a", "b", "c", "d", "e");
Collection<String> c2 = Arrays.asList("b", "c", "d", "e", "f");
Set<String> set = new HashSet<>(c1); //one loop over c1 to create the set - O(n)
List<String> differences = new LinkedList<>();
//one loop over c2 - O(m)
for( String e : c2 ) {
boolean removed = set.remove(e); //should be O(1) due to hashset
//if the element wasn't removed it was not in the set and thus not in c1
if( !removed ) {
differences.add(e); //should be O(1) due to linked list
}
}
//at this point set only contains elements not in c2 as those have been removed by the loop
differences.addAll(set); //at most O(n) if nothing got removed
如您所见,我们有 2 个 O(n) 和 1 个 O(m) 操作,因此总时间复杂度为 O(n + m)。
使用流,可以通过 Collectors.groupingBy
和 Collectors.counting()
确定出现的次数,然后过滤出现多次的任何字符串:
List<String> differences = Stream.concat(set1.stream(), set2.stream())
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) // Map<String, Long> -> key -> element, value -> count of occurrences
.entrySet().stream()
.filter(e -> e.getValue() == 1) // filter not unique elements from 2 sets
.map(Map.Entry::getKey)
.collect(Collectors.toList());
我回复晚了,但觉得代码更清晰易懂。
在这里您可以看到如何与 Java 集合进行并集和交集:
回到你的问题来了解两组的区别:
- 创建并集和交集
- 并集减去交集
在代码中表示:
Set union = new Set(set1);
union.addAll(set2);
Set intersection = new Set(set1);
intersection.retainAll(set2);
Set result = new Set(union);
result.removeAll(intersection);
现在你得到了两个集合所没有的所有东西,它应该包含 [a, f]。
假设我有两套:
Set<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c", "d", "e") );
Set<String> set2 = new HashSet<>(Arrays.asList("b", "c", "d", "e", "f") );
在性能方面比较两者并获得 List
差异的最简单和最好的方法是什么?
这意味着我应该得到一个包含 "a"
和 "f"
的列表。这里棘手的是,差异可能出现在任何一个列表中。
我只能让它与 for 循环一起工作,但必须有更简单的方法...
请按照我发送的屏幕截图进行操作 我认为这是使用 java 8 个流
的最简单方法是这样的吗?
public static void main(String[] args) {
Set<String> set1 = new HashSet<>(Arrays.asList("a", "b", "c", "d", "e") );
Set<String> set2 = new HashSet<>(Arrays.asList("b", "c", "d", "e", "f") );
//get intersection array
Set<String> listSame = new HashSet<>(set2);
listSame.retainAll(set1);
System.out.println(listSame);
//get union array
Set<String> listDiff = new HashSet<>(set1);
listDiff.addAll(set2);
// get difference
listDiff.removeAll(listSame);
System.out.println(listDiff);
}
最好的方法可能是使用并集和交集,然后求差。
实现此目的的一种方法是创建一组一个集合,遍历另一个集合并在删除元素时检查是否包含该元素:
Collection<String> c1 = Arrays.asList("a", "b", "c", "d", "e");
Collection<String> c2 = Arrays.asList("b", "c", "d", "e", "f");
Set<String> set = new HashSet<>(c1); //one loop over c1 to create the set - O(n)
List<String> differences = new LinkedList<>();
//one loop over c2 - O(m)
for( String e : c2 ) {
boolean removed = set.remove(e); //should be O(1) due to hashset
//if the element wasn't removed it was not in the set and thus not in c1
if( !removed ) {
differences.add(e); //should be O(1) due to linked list
}
}
//at this point set only contains elements not in c2 as those have been removed by the loop
differences.addAll(set); //at most O(n) if nothing got removed
如您所见,我们有 2 个 O(n) 和 1 个 O(m) 操作,因此总时间复杂度为 O(n + m)。
使用流,可以通过 Collectors.groupingBy
和 Collectors.counting()
确定出现的次数,然后过滤出现多次的任何字符串:
List<String> differences = Stream.concat(set1.stream(), set2.stream())
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting())) // Map<String, Long> -> key -> element, value -> count of occurrences
.entrySet().stream()
.filter(e -> e.getValue() == 1) // filter not unique elements from 2 sets
.map(Map.Entry::getKey)
.collect(Collectors.toList());
我回复晚了,但觉得代码更清晰易懂。
在这里您可以看到如何与 Java 集合进行并集和交集:
回到你的问题来了解两组的区别:
- 创建并集和交集
- 并集减去交集
在代码中表示:
Set union = new Set(set1);
union.addAll(set2);
Set intersection = new Set(set1);
intersection.retainAll(set2);
Set result = new Set(union);
result.removeAll(intersection);
现在你得到了两个集合所没有的所有东西,它应该包含 [a, f]。