我认为这些答案都忽略了一个技巧。
在他的经典著作《Effective Java》中,Bloch在第47条中写道,“知道并使用库”,“简而言之,不要重复造轮子”。他给出了几个非常清晰的原因。
这里有一些答案建议使用Apache Commons Collections库中的CollectionUtils
方法,但没有人注意到回答这个问题最美丽、优雅的方式:
Collection<Object> culprits = CollectionUtils.disjunction( list1, list2 );
if( ! culprits.isEmpty() ){
}
罪魁祸首: 即不共同存在于
Lists
中的元素。使用
CollectionUtils.intersection( list1, culprits )
和
CollectionUtils.intersection( list2, culprits )
相对简单地确定哪些罪犯属于
list1
,哪些属于
list2
。
然而,在类似{ "a", "a", "b" }
disjunction
with { "a", "b", "b" }的情况下,它往往会崩溃... 但这并不是软件的缺陷,而是所需任务的微妙/模糊本质所固有的。
您可以随时检查源代码 (l.287)以了解此类任务的生成方式,由Apache工程师制作。使用他们的代码的一个好处是,它将经过彻底的尝试和测试,已经预见并处理了许多边缘情况和问题。如果需要,您可以复制和调整此代码。
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来实现您想要的相等性...然后操作这些包装对象的集合。