如何获得包含两组之间差异的列表?

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.groupingByCollectors.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]。