在java中,获得两个集合之间对称差异的最佳方法是什么?
我想知道是否有一种快速/干净的方法可以得到两个集合之间的对称差 我有:在java中,获得两个集合之间对称差异的最佳方法是什么?,java,collections,set,Java,Collections,Set,我想知道是否有一种快速/干净的方法可以得到两个集合之间的对称差 我有: Set<String> s1 = new HashSet<String>(); s1.add("a"); s1.add("b"); s1.add("c"); Set<String> s2 = new HashSet<String>(); s2.add("b"); Set s1=new HashSet(); s1.添加(“a”); s1.添加(“b”); s1.添加(“c”)
Set<String> s1 = new HashSet<String>();
s1.add("a");
s1.add("b");
s1.add("c");
Set<String> s2 = new HashSet<String>();
s2.add("b");
Set s1=new HashSet();
s1.添加(“a”);
s1.添加(“b”);
s1.添加(“c”);
Set s2=新的HashSet();
s2.添加(“b”);
我需要像这样的东西:
Set<String> diff = Something.diff(s1, s2);
// diff would contain ["a", "c"]
Set diff=Something.diff(s1,s2);
//差异将包含[“a”、“c”]
我只想澄清一下,我需要对称的区别。您可以使用库中的一些函数(非常好,我强烈推荐!) 用于和的Javadocs
symmetricDifference()
确实如此,但是difference()
通常也很有用
这两种方法都返回一个实时视图,但例如,您可以对结果集调用.immutableCopy()
,以获得一个不变的集。如果您不需要视图,但需要可以修改的集合实例,请调用.copyInto(s3)
。有关这些方法,请参见
s1.addAll(s2);
s1.removeAll(s2);
应该有用。如果您可以使用,您正在寻找。它返回两个集合的对称差
如果不是,则将两个集合的交集(retainal
)减去(removeAll
)到两个集合的并集(addAll
):
Set intersection=新哈希集(set1);
交叉口。保留(set2);
Set difference=新的HashSet();
差异。添加全部(set1);
差异。添加全部(set2);
差异。移除所有(交叉点);
您想要的是
它返回一个非泛型的集合
而且
它返回一个不可修改的集合
,作为通用的集合。SetView
番石榴有点现代,支持仿制药,但这两种都可以用。在一个集合中循环并比较。 只有
O(n)
才能循环通过其中一个集合。考虑这个代码:
for (String key: oldSet) {
if (newSet.contains(key))
newSet.remove(key);
else
newSet.add(key);
}
而newSet
现在将只包含两个集合中唯一的条目。这很快,因为您只需要循环遍历其中一个集合中的元素,并且除非您明确需要一个副本,否则不必创建集合。public class Practice{
public class Practice {
public static void main(String[] args) {
Set<Integer> set1 = new HashSet<Integer>();
Set<Integer> set2 = new HashSet<Integer>();
set1.add(1);
set1.add(4);
set1.add(7);
set1.add(9);
set2.add(2);
set2.add(4);
set2.add(5);
set2.add(6);
set2.add(7);
symmetricSetDifference(set1, set2);
}
public static void symmetricSetDifference(Set<Integer>set1, Set<Integer>set2){
//creating a new set
Set<Integer> newSet = new HashSet<Integer>(set1);
newSet.removeAll(set2);
set2.removeAll(set1);
newSet.addAll(set2);
System.out.println(newSet);
}
公共静态void main(字符串[]args){
Set set1=新的HashSet();
Set set2=新的HashSet();
set1.添加(1);
set1.添加(4);
set1.添加(7);
set1.添加(9);
set2.添加(2);
set2.添加(4);
set2.添加(5);
set2.添加(6);
set2.添加(7);
对称性集差(set1,set2);
}
公共静态void symmetricSetDifference(集合1、集合2){
//创建新集合
Set newSet=newhashset(set1);
新闻集删除全部(set2);
set2.移除所有(set1);
newSet.addAll(set2);
System.out.println(新闻集);
}
}Java8解决方案
我们可以在某些类SetUtils(比如)
中编写两个实用程序方法(适用于java 8和更早版本),如下所示:
public static <T> Set<T> symmetricDifferenceJava8(final Set<T> setOne, final Set<T> setTwo) {
Set<T> result = new HashSet<>(setOne);
setTwo.stream().filter(not(resultSet::add)).forEach(resultSet::remove);
return result;
}
public static <T> Set<T> symmetricDifference(final Set<T> setOne, final Set<T> setTwo) {
Set<T> result = new HashSet<T>(setOne);
for (T element : setTwo) {
if (!result.add(element)) {
result.remove(element);
}
}
return result;
}
public static <T> Predicate<T> not(Predicate<T> t) {
return t.negate();
}
所有东西都在a
中,而不在b
中
>>> a = {1,2,3}
>>> b = {1,4,5}
>>>
>>> a - b
{2, 3}
>>> b - a
{4, 5}
a.symmetric\u difference(b)
是恰好在一个集合中的所有元素,例如a-b
和b-a
的并集
>>> a.symmetric_difference(b)
{2, 3, 4, 5}
>>> (a - b).union(b - a)
{2, 3, 4, 5}
来自io.datakernel.common.collection
public static <T> Set<T> difference(Set<? extends T> a, Set<? extends T> b) {
return a.stream().filter(t -> !b.contains(t)).collect(toSet());
}
publicstaticsetdifference(SetQuick&easy:您可以编写Set diff=newhashset(s1);diff.removeAll(s2);@polkageist:对于s1={“a”,“b”,“c”},s2={“b”,“d”}将失败。结果应该是{“a”,“c”,“d”}如果通过“difference”(cf.),OP意味着对称差,那么您是对的。然而,您可以通过(a-b)+(b-a)或(a+b)得到它-(A cap B)。我不知道用java实现这一点有什么更快的方法。java 8和java 11:谢谢,我实际上是在寻找一个可以为我实现这一点的库,因为这是我目前在支持泛型中所做的。对于S1={“A”,“B”,“c”},S2={“B”,“d”},这将失败。结果应该是{“A”,“c”,“d”}。这是一个不对称的差异。他想要对称的差异。刚刚阅读了javadoc for symetricDifference(),我有点担心这句话“如果set1和set2是基于不同等价关系的集(如HashSet、TreeSet和IdentityHashMap的键集都是这样),则结果是未定义的。”这听起来好像OP的情况(以及Sets.symmetricDifference()的情况)的结果是未定义的方法似乎没有那么有用。@Gus JavaDoc想说结果是未定义的,如果您对使用不同等价关系的两个不同集合使用该方法,例如,计算HashSet
和TreeSet
之间的差异可能会有问题。将该方法与两个HashSet
s或两个TreeSet
等都可以。@Gus此外,如果元素的compareTo()
方法和equals()
方法彼此一致(这是他们的文档强烈推荐的),那么将该方法与HashSet
和TreeSet
一起使用也可以。因此,只有在特殊情况下,该方法才能保证差分计算正确,在大多数实际情况下,该方法会很好地工作。我对该声明也有同样的担忧。感谢@PhilippWendler澄清这一点!尽管此代码可能会回答该问题,但提供了有关为什么和/或如何回答问题的其他上下文此操作将显著提高其长期价值。请您的答案添加一些解释。请注意,对于HashSet
,此操作仅为O(n)
,没有冲突。对于树集,所有三个操作add(key)
,都包含(key)
和remove(key)
将需要搜索树一次,即额外的O(n log n)
。
public class Practice {
public static void main(String[] args) {
Set<Integer> set1 = new HashSet<Integer>();
Set<Integer> set2 = new HashSet<Integer>();
set1.add(1);
set1.add(4);
set1.add(7);
set1.add(9);
set2.add(2);
set2.add(4);
set2.add(5);
set2.add(6);
set2.add(7);
symmetricSetDifference(set1, set2);
}
public static void symmetricSetDifference(Set<Integer>set1, Set<Integer>set2){
//creating a new set
Set<Integer> newSet = new HashSet<Integer>(set1);
newSet.removeAll(set2);
set2.removeAll(set1);
newSet.addAll(set2);
System.out.println(newSet);
}
public static <T> Set<T> symmetricDifferenceJava8(final Set<T> setOne, final Set<T> setTwo) {
Set<T> result = new HashSet<>(setOne);
setTwo.stream().filter(not(resultSet::add)).forEach(resultSet::remove);
return result;
}
public static <T> Set<T> symmetricDifference(final Set<T> setOne, final Set<T> setTwo) {
Set<T> result = new HashSet<T>(setOne);
for (T element : setTwo) {
if (!result.add(element)) {
result.remove(element);
}
}
return result;
}
public static <T> Predicate<T> not(Predicate<T> t) {
return t.negate();
}
public static <T> Set<T> symmetricDifferenceJava11(final Set<T> setOne, final Set<T> setTwo) {
Set<T> result = new HashSet<>(setOne);
setTwo.stream().filter(Predicate.not(resultSet::add)).forEach(resultSet::remove);
return result;
}
public class Practice {
public static void main(String[] args) {
Set<Integer> set1 = new HashSet<Integer>();
Set<Integer> set2 = new HashSet<Integer>();
set1.add(1);
set1.add(4);
set1.add(7);
set1.add(9);
set2.add(2);
set2.add(4);
set2.add(5);
set2.add(6);
set2.add(7);
symmetricSetDifference(set1, set2);
}
public static void symmetricSetDifference(Set<Integer>set1, Set<Integer>set2){
//creating a new set
Set<Integer> newSet = new HashSet<Integer>(set1);
newSet.removeAll(set2);
set2.removeAll(set1);
newSet.addAll(set2);
System.out.println(newSet);
}
a - b
>>> a = {1,2,3}
>>> b = {1,4,5}
>>>
>>> a - b
{2, 3}
>>> b - a
{4, 5}
>>> a.symmetric_difference(b)
{2, 3, 4, 5}
>>> (a - b).union(b - a)
{2, 3, 4, 5}
public static <T> Set<T> difference(Set<? extends T> a, Set<? extends T> b) {
return a.stream().filter(t -> !b.contains(t)).collect(toSet());
}