如果我有两个集合:
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 ?
如果我有两个集合:
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 ?
当前回答
参考Bojan Vukasovic的回答,这里有一个更完整的答案。
它实际上返回一个delta,提供添加和删除的元素列表。
将集合传递给delta方法的顺序很重要。
要获得delta:
Set<Integer> test1 = new HashSet<Integer>();
test1.add(1);
test1.add(2);
test1.add(3);
test1.add(9);
Set<Integer> test2 = new HashSet<Integer>();
test2.add(1);
test2.add(2);
test2.add(3);
test2.add(4);
test2.add(5);
var delta = Sets.delta(test1, test2);
delta.additions.equals(Set.of(4,5));
delta.subtractions.equals(Set.of(9));
package dev.onepub.util;
import java.util.HashSet;
import java.util.Set;
public class Sets
{
/**
* Calculates the delta of the two sets.
*
* The method assumes that you have an existing set
* that has been revised.
*
* The delta is expressed as:
* additions - the list of items FOUND in the revised set, that are not in the existing set.
* subtractions - the list of items NOT in the revised set, that are in the existing set.
*
* The existing and revised sets are left unchanged.
*
* @param <T>
* @param existing - the original set used as the baseline
* @param revised - the revised set which will be compared against the existing set.
* @return a SetDelta that describes the set of changes.
*/
static public <T> SetDelta<T> delta(Set<T> existing, Set<T> revised)
{
var additions = new HashSet<>(revised);
additions.removeAll(existing);
var subtractions = new HashSet<>(existing);
subtractions.removeAll(revised);
return new SetDelta<T>(additions, subtractions);
}
/**
* Describes the changes between two sets.
* @author bsutton
*
* @param <T> the type of entity held by the set.
*/
static public class SetDelta<T>
{
public SetDelta(HashSet<T> additions, HashSet<T> subtractions)
{
this.additions = additions;
this.subtractions = subtractions;
}
// The set of additional items
final public Set<T> additions;
// The set of removed items.
final public Set<T> subtractions;
}
}
单元测试
package dev.onepub.util;
import static org.junit.jupiter.api.Assertions.*;
import java.util.Set;
import org.junit.jupiter.api.Test;
class SetsTest
{
@Test
void test()
{
Set<Integer> existingState = Set.of(1, 2, 3, 4, 5);
Set<Integer> newState = Set.of(0, 5, 2, 11, 3, 99);
var delta = Sets.delta(existingState, newState);
assertEquals(delta.additions, Set.of(0, 99, 11));
assertEquals(delta.subtractions, Set.of(1, 4));
}
@Test
void testSame()
{
Set<Integer> existingState = Set.of(1,2);
Set<Integer> newState = Set.of(1,2);
var delta = Sets.delta(existingState, newState);
assertEquals(delta.additions, Set.of());
assertEquals(delta.subtractions, Set.of());
}
@Test
void testBothEmpty()
{
Set<Integer> existingState = Set.of();
Set<Integer> newState = Set.of();
var delta = Sets.delta(existingState, newState);
assertEquals(delta.additions, Set.of());
assertEquals(delta.subtractions, Set.of());
}
@Test
void testAddOne()
{
Set<Integer> existingState = Set.of();
Set<Integer> newState = Set.of(1);
var delta = Sets.delta(existingState, newState);
assertEquals(delta.additions, Set.of(1));
assertEquals(delta.subtractions, Set.of());
}
@Test
void testRemoveOne()
{
Set<Integer> existingState = Set.of(1);
Set<Integer> newState = Set.of();
var delta = Sets.delta(existingState, newState);
assertEquals(delta.additions, Set.of());
assertEquals(delta.subtractions, Set.of(1));
}
@Test
void testAddOneRemoveOne()
{
Set<Integer> existingState = Set.of(1);
Set<Integer> newState = Set.of(0);
var delta = Sets.delta(existingState, newState);
assertEquals(delta.additions, Set.of(0));
assertEquals(delta.subtractions, Set.of(1));
}
}
其他回答
试试这个
test2.removeAll(test1);
组# removeAll
从此集合中删除指定集合中包含的所有元素(可选操作)。如果指定的集合也是一个集合,则此操作将有效地修改该集合,使其值为两个集合的非对称集之差。
添加一个解决方案,我最近用过,没有看到这里提到。如果你有Apache Commons Collections可用,那么你可以使用SetUtils#difference方法:
// Returns all the elements of test2 which are not in test1
SetUtils.difference(test2, test1)
注意,根据文档,返回的集合是一个不可修改的视图:
返回一个不可修改的视图,其中包含给定集合的差值,用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-
您可以使用. 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);
Yes:
test2.removeAll(test1)
尽管这会使test2发生变异,所以如果需要保留它,请创建一个副本。
此外,您可能指的是<Integer>而不是<int>。
您可以使用Apache Commons CollectionUtils。disjunction来获得所有的差异,或者CollectionUtils。相减得到第一个集合中的差值。
<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));