哪个Java集合可以最快地删除元素?

时间:2019-06-05 22:17:29

标签: java collections

我正在寻找一个允许最快移除元素的集合。我在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会更快吗?或者,最快的删除一个元素的集合是什么?

3 个答案:

答案 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 会删除元素,然后添加元素要慢得多。这是因为数组在底层数组中不得有间隙。因此,如果您从头到尾删除所有元素,则需要转移元素。

此答案取决于您要删除基于索引还是基于值。 通常,基于索引的操作会更快,因为不需要进行扩展值比较。 由于如果要删除元素,必须先添加一次,因此考虑添加复杂性也是有帮助的

  • ArrayList:添加:O(n),摊销O(1)(实际上便宜)。 Remove始终为O(n),如果基于索引,则查找O(1),如果基于值,则查找O(n)

实践中摊销分析效果的示例:连续添加一百万个元素将产生一千万个副本。但是,副本数为O(log n),n为连续添加操作的数量。

  • LinkedList 添加:平均O(n),AddFirst / Last O(1),removeLast / First O(1),O(n),getFirstElement / GetLastElement O(1)。请注意:您必须知道,要搜索的元素位于结尾/开头,然后调用相应的方法。

到目前为止,如果您有很多连续的添加/删除操作和少量搜索操作(获取第一个或最后一个元素除外),建议您使用 LinkedList

如果您没有两个相同的对象,则(Object.equals(sameObject)会为精确的 same 对象返回true。您应该使用 LinkedHashSet 。它对所有操作都具有O(1),但是相等的对象只能包含一次。 不幸的是,这里不可能进行基于索引的搜索,方法也不同步。但是总会有一个权衡。

某些理论:根据here中提到的论文,我们不能做得更好,然后分摊Omega(log n)来任意添加和删除元素。