Java Commons Collections removeAll

33

CollectionUtils::removeAll() Commons Collections 3.2.1

这个方法好像和文档中说的相反:

从 collection 中移除 remove 中的元素。也就是说,此方法返回一个包含所有不在 remove 中的 c 中元素的集合。

下面这个 JUnit 测试会让人感到困惑:

@Test
public void testCommonsRemoveAll() throws Exception {
    String str1 = "foo";
    String str2 = "bar";
    String str3 = "qux";

    List<String> collection = Arrays.asList(str1, str2, str3);
    System.out.println("collection: " + collection);

    List<String> remove = Arrays.asList(str1);
    System.out.println("remove: " + remove);

    Collection result = CollectionUtils.removeAll(collection, remove);
    System.out.println("result: " + result);
    assertEquals(2, result.size());
}

代码运行失败,错误信息如下:

java.lang.AssertionError: 预期值为 <2>,但实际值为 <1>

并打印如下信息:

collection: [foo, bar, qux] 
remove: [foo] 
result: [foo]

从我对文档的阅读来看,我应该期望[bar, qux]。我错过了什么吗?


我更新了我的帖子以反映这一点,因为有人提醒了我 - 但是Apache Commons Collections 4.0于2013年11月发布,修复了这个问题。 - wkl
1个回答

45
2014年1月1日更新:Apache Commons Collections 4.0终于在2013年11月21日发布,其中包含了对此问题的修复。

链接至CollectionUtils.java

涉及到的代码行(1688-1691),并承认该方法以前存在问题:

/*
 ...
 * @since 4.0 (method existed in 3.2 but was completely broken)
 */
public static <E> Collection<E> removeAll(final Collection<E> collection, final Collection<?> remove) {
    return ListUtils.removeAll(collection, remove);
}

原始回答

不,你并不疯狂。 removeAll() 实际上(错误地)调用了 retainAll()

这是 CollectionUtils 中的一个 bug,影响版本 3.2。它已经修复,但只在 4.0 分支中。

https://issues.apache.org/jira/browse/COLLECTIONS-349

作为进一步的证明,这里是源代码链接:

http://svn.apache.org/repos/asf/commons/proper/collections/tags/COLLECTIONS_3_2/src/java/org/apache/commons/collections/CollectionUtils.java

检查这一行:

public static Collection removeAll(Collection collection, Collection remove) {
    return ListUtils.retainAll(collection, remove);
}

Yep...broken!


1
天啊!那怎么会被漏过去了?谢谢你提供的信息。点赞并接受你的回答。 - markdsievers
@markdsievers - 看起来需要编写单元测试或修复代码! - wkl
在我看来,这相当糟糕。犯错是可以理解的,但是原始问题的创建时间戳已经是“2006年8月2日17:37”,而至今仍然没有发布包含修复程序的生产版本。 - Stephen C
@StephenC - 这太糟糕了,即使是一个补丁版本也比等待主干版本的发布要好,而 Apache Commons Collections 上一次发布是在2008年4月的3.2.1版本。也许没有人认为这是个大问题,或者他们不知道它已经损坏了,导致代码库中到处都有问题。 - wkl
2
如果有人感兴趣,我的解决方案是直接使用此方法的意图,即ListUtils.removeAll(a,b)。 - markdsievers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接