我会说这些答案错过了一个窍门。
Bloch 在他的基本、精彩、简洁的Effective Java中,在第 47 项的标题“了解和使用库”中说,“总而言之,不要重新发明轮子”。他给出了几个非常明确的理由。
这里有一些答案建议来自CollectionUtils
Apache Commons Collections 库中的方法,但没有人发现回答这个问题的最漂亮、最优雅的方式:
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
// ... do something with the culprits, i.e. elements which are not common
}
罪魁祸首:即两者都不相同的元素Lists
。使用andlist1
来确定哪些罪魁祸首list2
是相对简单的。
然而,在 { "a", "a", "b" } 和 { "a", "b", "b" } 的情况下,它往往会崩溃……除非这不是软件的失败,而是所需任务的微妙之处/模糊性的性质所固有的。CollectionUtils.intersection( list1, culprits )
CollectionUtils.intersection( list2, culprits )
disjunction
您始终可以检查由 Apache 工程师制作的此类任务的源代码(l. 287)。使用他们的代码的一个好处是它已经过彻底的试验和测试,许多边缘情况和陷阱都可以预见和处理。如果需要,您可以根据需要复制和调整此代码。
NB 一开始我很失望,没有一种CollectionUtils
方法提供重载版本,使您能够强加自己的Comparator
(因此您可以重新定义equals
以适应您的目的)。
但是从 collections4 4.0 开始有一个新类,Equator
它“确定 T 类型的对象之间的相等性”。在检查 collections4 CollectionUtils.java 的源代码时,他们似乎将其与某些方法一起使用,但据我所知,这不适用于文件顶部的方法,使用CardinalityHelper
类...包括disjunction
和intersection
。
我推测 Apache 的人还没有解决这个问题,因为它不是微不足道的:你必须创建类似“AbstractEquatingCollection”类的东西,而不是使用其元素的固有方法equals
和hashCode
方法而是必须使用那些的Equator
所有基本方法,例如add
,contains
等。注意实际上,当您查看源代码时,AbstractCollection
并没有实现add
,也没有实现它的抽象子类,例如AbstractSet
...您必须等到具体的类,例如HashSet
和ArrayList
之前add
被实施。很头疼。
我想,与此同时,请注意这个空间。显而易见的临时解决方案是将所有元素包装在一个定制的包装类中,该类使用equals
并hashCode
实现你想要的那种平等……然后操纵Collections
这些包装对象。