209

所以如果我有两套:

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);

有没有办法比较它们并且只返回一组 4 和 5?

4

9 回答 9

251

尝试这个

test2.removeAll(test1);

设置#removeAll

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

于 2013-09-05T19:42:42.420 回答
149

如果您使用 Guava(前 Google Collections)库,则有一个解决方案:

SetView<Number> difference = com.google.common.collect.Sets.difference(test2, test1);

返回SetView的是 a Set,它是一个实时表示,您可以将其设为不可变或复制到另一个集合。test1并且test2完好无损。

于 2015-04-15T08:09:42.590 回答
18

是的:

test2.removeAll(test1)

虽然这会 mutate test2,但如果您需要保留它,请创建一个副本。

另外,您可能的意思是<Integer>代替<int>.

于 2013-09-05T19:42:36.147 回答
15

爪哇 8

我们可以使用removeIf,它需要一个谓词来编写一个实用方法:

// 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;
}

如果我们仍然处于某个以前的版本,那么我们可以使用 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;
}
于 2018-09-11T04:54:19.750 回答
13

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

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.4</version>
</dependency>

以下是如何执行此操作的示例:

import org.apache.commons.collections4.CollectionUtils;
import java.util.List;

var collection1 = List.of(-1, 0, 1, 2, 3, 4, 5);
var collection2 = List.of(       1, 2, 3, 4, 5, 6, 7, 8, 9);

// [-1, 0, 1, 2, 3, 4, 5]
System.out.println(collection1);
// [1, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println(collection2);

// [-1, 0]
System.out.println(CollectionUtils.subtract(collection1, collection2));
// [6, 7, 8, 9]
System.out.println(CollectionUtils.subtract(collection2, collection1));

// [1, 2, 3, 4, 5]
System.out.println(CollectionUtils.retainAll(collection1, collection2));
// [1, 2, 3, 4, 5]
System.out.println(CollectionUtils.retainAll(collection2, collection1));

// [-1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9]
System.out.println(CollectionUtils.collate(collection1, collection2));
// [-1, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9]
System.out.println(CollectionUtils.collate(collection2, collection1));

// [-1, 0, 6, 7, 8, 9]
System.out.println(CollectionUtils.disjunction(collection1, collection2));
// [-1, 0, 6, 7, 8, 9]
System.out.println(CollectionUtils.disjunction(collection2, collection1));

// [1, 2, 3, 4, 5]
System.out.println(CollectionUtils.intersection(collection1, collection2));
// [1, 2, 3, 4, 5]
System.out.println(CollectionUtils.intersection(collection2, collection1));

// [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println(CollectionUtils.union(collection1, collection2));
// [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
System.out.println(CollectionUtils.union(collection2, collection1));
于 2018-09-14T09:24:29.747 回答
10

添加一个我最近自己使用过但在这里没有提到的解决方案。如果您有可用的 Apache Commons Collections,那么您可以使用以下SetUtils#difference方法:

// Returns all the elements of test2 which are not in test1
SetUtils.difference(test2, test1) 

请注意,根据文档,返回的集合是不可修改的视图:

返回一个不可修改的视图,其中包含给定 Sets 的差异,用 a \ b(或 a - b)表示。返回的视图包含 a 中不属于 b 的所有元素。

完整文档:https ://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/SetUtils.html#difference-java.util.Set-java.util.Set-

于 2021-01-06T17:46:55.653 回答
3

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

public class AddAndRemove {

  static Set<Integer> existingState = Set.of(1,2,3,4,5);
  static Set<Integer> newState = Set.of(0,5,2,11,3,99);

  public static void main(String[] args) {

    Set<Integer> add = new HashSet<>(newState);
    add.removeAll(existingState);

    System.out.println("Elements to add : " + add);

    Set<Integer> remove = new HashSet<>(existingState);
    remove.removeAll(newState);

    System.out.println("Elements to remove : " + remove);

  }
}

结果会输出这个:

Elements to add : [0, 99, 11]
Elements to remove : [1, 4]
于 2019-11-08T09:55:46.217 回答
1

如果您使用的是 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());
}
于 2013-09-05T19:43:57.567 回答
0

您可以使用 .addAll() 建立联合,使用 .retainAll() 建立交集,并使用 .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);
于 2020-12-12T07:21:46.323 回答