简体   繁体   English

Java Array/ArrayList/LinkedList 性能

[英]Java Array/ArrayList/LinkedList performance

I used the following code to test the performance between Array/ArrayList/LinkedList我使用下面的代码来测试 Array/ArrayList/LinkedList 之间的性能

import java.util.ArrayList;
import java.util.LinkedList;

public class Main3 {
    public static void main(String[] args) throws Exception{

        int n = 20000000;
        long bt = 0, et = 0;

        int[] a0 = new int[n];
        ArrayList<Integer> a1 = new ArrayList<>(n);
        LinkedList<Integer> a2 = new LinkedList<>();
        Integer[] a3 = new Integer[n];

        bt = System.currentTimeMillis();
        for(int i=0; i<n; i++){
            a0[i] = i;
        }
        et = System.currentTimeMillis();
        System.out.println("===== loop0 time =======" + (et - bt));

        bt = System.currentTimeMillis();
        for(int i=0; i<n; i++){
            a1.add(i);
        }
        et = System.currentTimeMillis();
        System.out.println("===== loop1 time =======" + (et - bt));

        bt = System.currentTimeMillis();
        for(int i=0; i<n; i++){
            a2.add(i);
        }
        et = System.currentTimeMillis();
        System.out.println("===== loop2 time =======" + (et - bt));


        bt = System.currentTimeMillis();
        for(int i=0; i<n; i++){
            a3[i] = i;
        }
        et = System.currentTimeMillis();
        System.out.println("===== loop3 time =======" + (et - bt));
    }
}

The result is结果是

===== loop0 time =======11
===== loop1 time =======6776
===== loop2 time =======17305
===== loop3 time =======56

Why the ArralyList/LinkedList is so slower than array?为什么 ArralyList/LinkedList 比数组慢? How could I improve the performance.我怎样才能提高性能。

env: Java: jdk1.8.0_231环境:Java:jdk1.8.0_231

Thanks谢谢

There are potential inaccuracies in your benchmark, but the overall ranking of the results is probably correct.您的基准测试可能存在不准确之处,但结果的总体排名可能是正确的。 You may get faster results for all of the benchmarks if you "warm-up" the code before taking timings to allow the JIT compiler to generate native code and optimise it.如果您在计时之前“预热”代码以允许 JIT 编译器生成本机代码并对其进行优化,您可能会更快地获得所有基准测试的结果。 Some benchmark results may be closer or even equal.一些基准测试结果可能更接近甚至相等。

Iterating over an int array is going to be much faster than iterating over a List of Integer objects.遍历int数组比遍历Integer对象List要快得多。 A LinkedList is going to be slowest of all. LinkedList将是最慢的。 These statements assume the optimiser doesn't make radical changes.这些陈述假设优化器没有做出根本性的改变。

Let's look at why:让我们看看为什么:

An int array ( int[] ) is a contiguous area of memory containing your 4 byte ints arranged end-to-end.一个int数组 ( int[] ) 是一个连续的内存区域,包含端到端排列的 4 字节整数。 The loop to iterate over this and set the elements just has to work its way through the block of memory setting each 4 bytes in turn.迭代它并设置元素的循环只需要通过内存块依次设置每 4 个字节。 In principle an index check is required, but in practice the optimiser can realise this isn't necessary and remove it.原则上索引检查是必需的,但实际上优化器可以意识到这不是必需的并将其删除。 The JIT compiler is well able to optimise this kind of thing based on native CPU instructions. JIT 编译器能够很好地基于原生 CPU 指令优化这类事情。

An ArrayList of Integer objects contains an array of references which point to individual Integer objects (or are null). Integer对象的ArrayList包含指向单个Integer对象(或为 null)的引用数组。 Each Integer object will have to be allocated separately (although Java can re-use Integers of small numbers).每个Integer对象都必须单独分配(尽管 Java 可以重用小整数)。 There is an overhead to allocate new objects and in addition the reference may be 8 bytes instead of 4. Also, if the list size is not specified (though it is in your case) the internal array may need to be reallocated.分配新对象会产生开销,此外引用可能是 8 个字节而不是 4 个字节。此外,如果未指定列表大小(尽管在您的情况下),则可能需要重新分配内部数组。 There is an overhead due to calling the add method instead of assigning to the array directly (the optimizer may remove this though).由于调用add方法而不是直接分配给数组会产生开销(优化器可能会删除它)。

Your array of Integer benchmark is similar to the array list but doesn't have the overhead of the list add method call (which has to track the list size).您的Integer基准数组类似于数组列表,但没有列表添加方法调用的开销(必须跟踪列表大小)。 Probably your benchmark overstates the difference between this array and the array list though.可能你的基准夸大了这个数组和数组列表之间的区别。

A LinkedList is the worst case. LinkedList是最坏的情况。 Linked lists are optimised for inserting in the middle.链接列表针对在中间插入进行了优化。 They have references to point to the next item in the list and nodes to hold those references in addition to the Integer object that needs allocating.除了需要分配的Integer对象之外,它们还具有指向列表中下一项的引用和用于保存这些引用的节点。 This is a big memory overhead that also requires some initialisation and you would not use a linked list unless you were expecting to insert a lot of elements into the middle of the list.这是一个很大的内存开销,还需要一些初始化,除非您希望将大量元素插入列表的中间,否则您不会使用链表。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM