我正在寻找一个允许最快移除元素的集合。我在100万行上测试了ArrayList,结果发现删除第一个元素比删除最后一个要快。删除一百万个元素大约需要50秒
import java.util.ArrayList;
public class TestArray {
final int numberOfElements = 1000000;
public void testArray () {
// test array
ArrayList<String> testArray = new ArrayList<String>();
for (int i = 0; i < numberOfElements; i++) {
testArray.add("" + Math.random());
}
// testing speed when removing the first element
long startTime = System.currentTimeMillis();
while (true) {
if (testArray.isEmpty()) {
System.out.println("Milliseconds to fisnish when removing the first element " + (System.currentTimeMillis() - startTime));
break;
}
else {
String testString = testArray.get(0);
testArray.remove(testString);
}
}
testArray = new ArrayList<String>();
for (int i = 0; i < numberOfElements; i++) {
testArray.add("" + Math.random());
}
// testing speed when removing the last element
long startTime2 = System.currentTimeMillis();
while (true) {
if (testArray.isEmpty()) {
System.out.println("Milliseconds to fisnish when removing the last element " + (System.currentTimeMillis() - startTime2));
break;
}
else {
String testString = testArray.get(testArray.size()-1);
testArray.remove(testString);
}
}
}
}
但是我不确定这是否是最快的方法。 50秒是最快的方法吗?还是有更好的集合,例如LinkedList
会更快吗?或者,最快的删除一个元素的集合是什么?
答案 0 :(得分:2)
1)您应该考虑 LinkedList ,它具有 O(1)大O性能,可用于删除操作(下面的解释)< / strong>,而ArrayList为O(n)。
2)如果您对重复项不感兴趣,可以尝试使用HashSet。
LinkedList删除:
1)由于不需要遍历,因此在开始和结束时删除LinkedList的时间都是固定的。
2)删除中间元素需要更长的时间,因为需要首先找到该元素。
3)如果要删除的位置有一个迭代器,则删除是固定时间。
答案 1 :(得分:1)
性能最佳的集合是TreeSet,因为如果根据Comparable / Comparator插入对象,则将对集合进行排序。
我的时间: 数组列表 删除第一个元素698时要变细的毫秒数 删除最后一个元素121960所需的毫秒数
TreeSet: 移除第一个元素时需要花费的毫秒数55 删除最后一个元素50所需的毫秒数
警告:使用此解决方案,您在集合中不能有重复的对象。
@Test
public void testTreeSet() {
/* RESULTS
* Milliseconds to fisnish when removing the first element 55
* Milliseconds to fisnish when removing the last element 50
*/
// test array
TreeSet<String> testArray = new TreeSet<String>();
int numberOfElements = 100000;
for (int i = 0; i < numberOfElements; i++) {
testArray.add("" + Math.random());
}
// testing speed when removing the first element
long startTime = System.currentTimeMillis();
while (true) {
if (testArray.isEmpty()) {
System.out.println("Milliseconds to fisnish when removing the first element "
+ (System.currentTimeMillis() - startTime));
break;
} else {
//String testString = testArray.get(0);
String testString = testArray.first();
testArray.remove(testString);
}
}
testArray = new TreeSet<String>();
for (int i = 0; i < numberOfElements; i++) {
testArray.add("" + Math.random());
}
// testing speed when removing the last element
long startTime2 = System.currentTimeMillis();
while (true) {
if (testArray.isEmpty()) {
System.out.println("Milliseconds to fisnish when removing the last element "
+ (System.currentTimeMillis() - startTime2));
break;
} else {
//String testString = testArray.get(testArray.size() - 1);
String testString = testArray.last();
testArray.remove(testString);
}
}
}
答案 2 :(得分:1)
首先:基准测试一定有问题, ArrayList 会删除元素,然后添加元素要慢得多。这是因为数组在底层数组中不得有间隙。因此,如果您从头到尾删除所有元素,则需要转移元素。
此答案取决于您要删除基于索引还是基于值。 通常,基于索引的操作会更快,因为不需要进行扩展值比较。 由于如果要删除元素,必须先添加一次,因此考虑添加复杂性也是有帮助的
实践中摊销分析效果的示例:连续添加一百万个元素将产生一千万个副本。但是,副本数为O(log n),n为连续添加操作的数量。
到目前为止,如果您有很多连续的添加/删除操作和少量搜索操作(获取第一个或最后一个元素除外),建议您使用 LinkedList 。
如果您没有两个相同的对象,则(Object.equals(sameObject)
会为精确的 same 对象返回true
。您应该使用 LinkedHashSet 。它对所有操作都具有O(1),但是相等的对象只能包含一次。
不幸的是,这里不可能进行基于索引的搜索,方法也不同步。但是总会有一个权衡。
某些理论:根据here中提到的论文,我们不能做得更好,然后分摊Omega(log n)来任意添加和删除元素。