为什么在Java 8中插入ArrayList的速度比插入LinkedList的速度快?

时间:2018-12-07 17:06:40

标签: java performance arraylist linked-list

我认为插入LinkedList应该比插入ArrayList更快,因为插入LinkedList仅需要复制引用,而插入ArrayList除了复制引用之外还需要创建一堆新数组。但是我创建了Java代码来测试这一点,但发现却相反,插入ArrayList比插入LinkedList更快。

import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

class ListPerformanceTester {
    public static void main(String[] args) {
        System.out.println("Time to perform ten million insertions using LinkedList: " +
                timeToPerformTenMillionInsertionsUsing(new LinkedList<>()));
        System.out.println("Time to perform ten million insertions using ArrayList: " +
                timeToPerformTenMillionInsertionsUsing(new ArrayList<>()));
    }

    private static long timeToPerformTenMillionInsertionsUsing(List<String> list) {
        Instant start = Instant.now();
        for (int i = 0; i < 10000000; ++i) {
            list.add("");
        }
        return Duration.between(start, Instant.now()).toMillis();
    }
}

运行3次的结果:

Time to perform ten million insertions using ArrayList: 135
Time to perform ten million insertions using LinkedList: 1321

Time to perform ten million insertions using ArrayList: 126
Time to perform ten million insertions using LinkedList: 1094

Time to perform ten million insertions using ArrayList: 125
Time to perform ten million insertions using LinkedList: 1086

我什至试图反转插入的顺序,以防万一有效果并且LinkedList花费的时间更长:

Time to perform ten million insertions using LinkedList: 2642
Time to perform ten million insertions using ArrayList: 402

为什么插入ArrayList的速度比插入LinkedList的速度快?

$ java -version
java version "1.8.0_171"
Java(TM) SE Runtime Environment (build 1.8.0_171-b11)
Java HotSpot(TM) 64-Bit Server VM (build 25.171-b11, mixed mode)

1 个答案:

答案 0 :(得分:-1)

...但是... it is faster。链接列表在前面或后面的插入时间为constant time。数组列表插入为amortized constant time,但要注意的是,如果达到一定容量,它将使内部数组的大小加倍,并且复制其必须跟踪的所有先前值of,即O(k),其中k是当前列表的大小。

此外,在实际运行测试方法之前,让我们谈谈测试方法中的明显缺陷-you don't warm up just-in-time optimizer。这些数字看起来像是在运行基准测试,而JIT优化可以使您的代码产生奇怪的事情。

这样,如果我们通过运行100次来预热代码,然后在每次测试运行之后有礼貌地要求Java进行垃圾回收(并且知道它可能会说“否”),我们可以更好的图片。

class ListPerformanceTester {
    public static void main(String[] args) {
        System.out.println("Warming up by running 100 times...");
        for(int i = 0; i < 100; i++) {
            // warm up
            timeToPerformTenMillionInsertionsUsing(new LinkedList<>());
            timeToPerformTenMillionInsertionsUsing(new ArrayList<>());
        }

        System.out.println("Starting test.");
        for(int i = 0; i < 10; i++) {
            System.out.println("Time to perform ten million insertions using LinkedList: " +
                                       timeToPerformTenMillionInsertionsUsing(new LinkedList<>()));
            System.out.println("Time to perform ten million insertions using ArrayList: " +
                                       timeToPerformTenMillionInsertionsUsing(new ArrayList<>()));
            System.out.println();

            System.gc();
        }

    }

    private static long timeToPerformTenMillionInsertionsUsing(List<String> list) {
        Instant start = Instant.now();
        for (int i = 0; i < 10000000; ++i) {
            list.add("");
        }
        return Duration.between(start, Instant.now()).toMillis();
    }
}

这是我的机器(这是Intel Core i7-7820HQ)的十个结果:

Warming up by running 100 times...
Starting test.
Time to perform ten million insertions using LinkedList: 40
Time to perform ten million insertions using ArrayList: 45

Time to perform ten million insertions using LinkedList: 38
Time to perform ten million insertions using ArrayList: 45

Time to perform ten million insertions using LinkedList: 41
Time to perform ten million insertions using ArrayList: 46

Time to perform ten million insertions using LinkedList: 41
Time to perform ten million insertions using ArrayList: 45

Time to perform ten million insertions using LinkedList: 38
Time to perform ten million insertions using ArrayList: 45

Time to perform ten million insertions using LinkedList: 38
Time to perform ten million insertions using ArrayList: 44

Time to perform ten million insertions using LinkedList: 38
Time to perform ten million insertions using ArrayList: 44

Time to perform ten million insertions using LinkedList: 41
Time to perform ten million insertions using ArrayList: 45

Time to perform ten million insertions using LinkedList: 38
Time to perform ten million insertions using ArrayList: 44

Time to perform ten million insertions using LinkedList: 39
Time to perform ten million insertions using ArrayList: 47