我有以下代码,我在使用superList和subList,我想检查subList实际上是superList的subList。
我的对象没有实现hashCode或equals方法。我在测试中创建了类似的情况。当我运行测试时,结果显示JDK集合和常见集合的结果之间存在非常大的性能差异。运行测试后,我得到以下输出。
使用Java Collection API 8953 MilliSeconds&结果是真的 使用Commons Collection API 78 MilliSeconds&结果是真的
我的问题是为什么是java集合,处理containsAll操作的速度很慢。我在那里做错了吗?我无法控制集合类型我从遗留代码中获取它。我知道如果我使用HashSet作为superList,那么使用JDK containsAll操作我会获得很大的性能提升,但不幸的是,这对我来说是不可能的。
package com.mycompany.tests;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import org.apache.commons.collections.CollectionUtils;
import org.junit.Before;
import org.junit.Test;
public class CollectionComparison_UnitTest {
private Collection<MyClass> superList = new ArrayList<MyClass>();
private Collection<MyClass> subList = new HashSet<MyClass>(50000);
@Before
public void setUp() throws Exception {
for (int i = 0; i < 50000; i++) {
MyClass myClass = new MyClass(i + "A String");
superList.add(myClass);
subList.add(myClass);
}
}
@Test
public void testIt() {
long startTime = System.currentTimeMillis();
boolean isSubList = superList.containsAll(subList);
System.out.println("Time Lapsed with Java Collection API "
+ (System.currentTimeMillis() - startTime)
+ " MilliSeconds & Result is " + isSubList);
startTime = System.currentTimeMillis();
isSubList = CollectionUtils.isSubCollection(subList, superList);
System.out.println("Time Lapsed with Commons Collection API "
+ (System.currentTimeMillis() - startTime)
+ " MilliSeconds & Result is " + isSubList);
}
}
class MyClass { String myString;
MyClass(String myString) {
this.myString = myString;
}
String getMyString() {
return myString;
}
}
答案 0 :(得分:4)
不同的算法:
ArrayList.containsAll()
提供 O(N * N),而CollectionUtils.isSubCollection()
提供 O(N + N + N)。
答案 1 :(得分:3)
您至少应该以相反的顺序尝试测试。您的结果可能只是表明JIT编译器正在完成其工作: - )
答案 2 :(得分:2)
ArrayList.containsAll继承自AbstractCollection.containsAll,是一个检查行中所有元素的简单循环。每个步骤都是慢速线性搜索。我不知道CollectionUtils是如何工作的,但是使用简单的循环并不难做得快。将第二个List转换为HashSet是一个肯定的胜利。对这两个列表进行排序并通过它们可能会更好。
CollectionUtils source code表明了这一点。他们将这两个系列转换为“基数图”,这对于许多操作来说都是一种简单而通用的方式。在某些情况下,这可能不是一个好主意,例如,当第一个列表为空或非常短时,您实际上是在闲置时间。在你的情况下,与AbstractCollection.containsAll相比,这是一个巨大的胜利,但你可以做得更好。