Java 获得两组之间的差异

Java 获得两组之间的差异,java,set,Java,Set,如果我有两套: Set<Integer> test1 = new HashSet<Integer>(); test1.add(1); test1.add(2); test1.add(3); Set<Integer> test2 = new HashSet<Integer>(); test2.add(1); test2.add(2); test2.add(3); test2.add(4); test2.add(5); Set test1=new

如果我有两套:

Set<Integer> test1 = new HashSet<Integer>();
test1.add(1);
test1.add(2);
test1.add(3);

Set<Integer> test2 = new HashSet<Integer>();
test2.add(1);
test2.add(2);
test2.add(3);
test2.add(4);
test2.add(5);
Set test1=new HashSet();
test1.add(1);
测试1.添加(2);
测试1.添加(3);
Set test2=新的HashSet();
测试2.添加(1);
test2.add(2);
测试2.添加(3);
测试2.添加(4);
测试2.添加(5);
有没有办法比较它们,只返回一组4和5?

是:

test2.removeAll(test1)
虽然这将使test2发生变异,但如果需要保留它,请创建一个副本

另外,您可能是指
而不是

试试这个

test2.removeAll(test1);

从此集合中删除指定集合中包含的所有元素(可选操作)。如果指定的集合也是一个集合,则此操作会有效地修改此集合,使其值为两个集合的非对称集合差


如果您使用的是Java 8,您可以尝试以下方法:

public Set<Number> difference(final Set<Number> set1, final Set<Number> set2){
    final Set<Number> larger = set1.size() > set2.size() ? set1 : set2;
    final Set<Number> smaller = larger.equals(set1) ? set2 : set1;
    return larger.stream().filter(n -> !smaller.contains(n)).collect(Collectors.toSet());
}
公共设置差异(最终设置集1、最终设置集2){
最终设置更大=set1.size()>set2.size()?set1:set2;
最后一组较小=较大。等于(set1)?set2:set1;
返回较大的.stream().filter(n->!较小的.contains(n)).collect(Collectors.toSet());
}
如果您使用Guava(以前的谷歌收藏)库,有一个解决方案:

SetView<Number> difference = com.google.common.collect.Sets.difference(test2, test1);
SetView difference=com.google.common.collect.Sets.difference(test2,test1);
返回的
SetView
是一个
Set
,它是一个活动表示,您可以使其不可变或复制到另一个集合<代码>测试1和
测试2
保持不变。

Java8 我们可以利用它作为谓词来编写实用程序方法,如下所示:

// computes the difference without modifying the sets
public static <T> Set<T> differenceJava8(final Set<T> setOne, final Set<T> setTwo) {
     Set<T> result = new HashSet<T>(setOne);
     result.removeIf(setTwo::contains);
     return result;
}
//在不修改集合的情况下计算差异
公共静态集差异java8(最终集集合一,最终集集合二){
设置结果=新哈希集(setOne);
result.removeIf(setTwo::contains);
返回结果;
}
如果我们仍然使用以前的版本,那么我们可以将removeAll用作:

public static <T> Set<T> difference(final Set<T> setOne, final Set<T> setTwo) {
     Set<T> result = new HashSet<T>(setOne);
     result.removeAll(setTwo);
     return result;
}
公共静态设置差异(最终设置集一、最终设置集二){
设置结果=新哈希集(setOne);
结果:移除所有(设置2);
返回结果;
}

您可以使用
CollectionUtils.disjunction
获取所有差异,或者使用
CollectionUtils.subtract
获取第一个集合中的差异

以下是如何做到这一点的示例:

    var collection1 = List.of(1, 2, 3, 4, 5);
    var collection2 = List.of(2, 3, 5, 6);
    System.out.println(StringUtils.join(collection1, " , "));
    System.out.println(StringUtils.join(collection2, " , "));
    System.out.println(StringUtils.join(CollectionUtils.subtract(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.retainAll(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.collate(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.disjunction(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.intersection(collection1, collection2), " , "));
    System.out.println(StringUtils.join(CollectionUtils.union(collection1, collection2), " , "));

这里仅举一个例子(系统处于
existingState
,我们希望找到要删除的元素(不在
newState
中但在
existingState
中存在的元素)和要添加的元素(在
newState
中但在
existingState
中不存在的元素):


可以使用两个集合中的.addAll()创建一个并集,使用.retainal()创建一个交集,并使用.removeIf()从并集中删除交集(或重复的元素)

HashSet union = new HashSet(group1);
union.addAll(group2);
        
System.out.println("Union: " + union);
        
HashSet intersection = new HashSet(group1);
intersection.retainAll(group2);
        
System.out.println("Intersection: " + intersection);
        
HashSet difference = new HashSet(union);
difference.removeIf(n -> (difference.contains(intersection)));
        
System.out.println("Difference: " + difference);

添加一个我最近使用过的解决方案,这里没有提到。如果您有可用的Apache Commons集合,则可以使用
SetUtils\difference
方法:

// Returns all the elements of test2 which are not in test1
SetUtils.difference(test2, test1) 
请注意,根据文档,返回的集合是不可修改的视图:

返回一个不可修改的视图,该视图包含给定集合的差异,用a\b(或a-b)表示。 返回的视图包含不是b成员的a的所有元素


完整文档:

可能的重复不是完全重复:对称差分和差分不一样。如果
test1
包含
6
,答案会是4,5,6吗?也就是说,如果test1包含6,我希望答案仍然是4,5。Java 8:@Downvoter:也许你有未能意识到其他答案没有检查哪个
集合
更大…因此,如果您试图从较大的
集合
中减去较小的
集合
,您将收到不同的结果。您假设该函数的使用者总是希望减去较小的集合。集合差异为anticommutative().A-B!=B-ARegardless不管您实现了哪种差异变体,我将使用
公共静态集差异(final Set set1,final Set set2){
作为签名,该方法随后可用作通用效用函数。这将导致意外的结果,因为用户可能会在不知情的情况下切换差分操作的顺序。从较小的集合中减去较大的集合在数学上有很好的定义,并且有大量的用例。集合差分不是一种交换假设运算。操作数的顺序很重要。OP问题和注释表明他想做test2-test1。你的答案是错误的…至少如果是符号差,但它不起作用。但我认为这将是一个很好的功能,在java中构建像并集、差分这样的集合运算on将修改集合,在许多情况下我们并不希望这样。当Java没有定义
联合
交叉
差异
时,它怎么能厚颜无耻地将此数据结构称为
集合
!这个解决方案不是完全正确的。因为test1和test2的顺序不同。@datv resu这会有所不同。
test1.removeAll(test2)
是一个空集。
test2.removeAll(test1)
{4,5}
@BojanPetkovic这给出了
test2
中不在
test1
中的元素,这正是OP所要求的。请注意,test2和test1的顺序很重要。还有顺序不重要的地方。
symmetricDifference()
将带来除交叉点以外的所有东西,这不是原始问题所要求的。收集utils来自哪个项目?我是否必须假设它来自Apache Commons收集?
HashSet union = new HashSet(group1);
union.addAll(group2);
        
System.out.println("Union: " + union);
        
HashSet intersection = new HashSet(group1);
intersection.retainAll(group2);
        
System.out.println("Intersection: " + intersection);
        
HashSet difference = new HashSet(union);
difference.removeIf(n -> (difference.contains(intersection)));
        
System.out.println("Difference: " + difference);
// Returns all the elements of test2 which are not in test1
SetUtils.difference(test2, test1)