在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);
应该工作。