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