我会说这些答案错过了一个窍门。
Bloch 在他的基本、精彩、简洁的Effective Java中,在第 47 项的标题“了解和使用库”中说,“总而言之,不要重新发明轮子”。他给出了几个非常明确的理由。
这里有一些答案建议来自CollectionUtilsApache 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这些包装对象。