在java中获得两组对称差异的最佳方法是什么?

我想知道是否有一个快速/干净的方式来获得两套之间的差异?

我有:

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<String> diff = Something.diff(s1, s2); // diff would contain ["a", "c"] 

只是为了澄清我需要对称的差异。

你可以使用谷歌Guava库中的一些function(这真是太好了,我强烈推荐它!):

 Sets.difference(s1, s2); Sets.symmetricDifference(s1, s2); 

Javadocs 差异()和symmetricDifference()

symmetricDifference()完全符合你的要求 ,但是difference()也常常有帮助。

这两个方法都返回一个实时视图,但是您可以在结果集上调用.immutableCopy()来获取一个不变的集合。 如果你不想要一个视图,但需要一个你可以修改的实例,调用.copyInto(s3) 。 请参阅SetView这些方法。

你想要对称的差异 。

 public static <T> Set<T> diff(final Set<? extends T> s1, final Set<? extends T> s2) { Set<T> symmetricDiff = new HashSet<T>(s1); symmetricDiff.addAll(s2); Set<T> tmp = new HashSet<T>(s1); tmp.retainAll(s2); symmetricDiff.removeAll(tmp); return symmetricDiff; } 

如果你想要一个库, Apache Commons CollectionUtils有

 CollectionUtils.disjunction(s1, s2) 

它返回一个非genericsCollection

和番石榴集

 Sets.symmetricDifference(s1, s2) 

它返回一个不可修改的Set作为一个通用的Sets.SetView

番石榴是一个更现代化,支持仿制药,但其中任何一个将工作。

如果你可以使用Apache-Commons Collections ,你正在寻找CollectionUtils.disjunction(Collection a, Collection b) 。 它返回两个集合的对称差异。

如果不是,则将这两个集合的交集( retainAll )减去( retainAll )的并集( addAll ):

 Set<String> intersection = new HashSet<String>(set1); intersection.retainAll(set2); Set<String> difference = new HashSet<String>(); difference.addAll(set1); difference.addAll(set2); difference.removeAll(intersection); 

循环一组并比较。

只有O(n)才能通过其中的一个循环。 考虑这个代码:

 for (String key: oldSet) { if (newSet.contains(key)) newSet.remove(key); else newSet.add(key); } 

newSet现在只包含来自两个集合的唯一条目。 这很快,因为你只需要遍历其中一个集合中的元素,而且除非明确需要副本,否则不必创build集合。

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

}

 s1.addAll(s2); s1.removeAll(s2); 

应该工作。