The Way to Pro Full Stack

When we are going to use a List, we were taught to write the following the code:

List list = new ArrayList<>();

And to avoid another List implementation: LinkedList, is this always true and why?

JDK ArrayList internal

ArrayList is an array based implementation, but array can only have fixed length, so what will happen is we try to add a new element? The solution is quite simple, just create a new array with longer length, and copy the elements from old array to the new array. We can check the JDK source code to have a look.

privatevoidgrow(intminCapacity){//minCapacity = size + 1// This is the interesting part, the new array size is not just oldCapacity++, but oldCapacity + (oldCapacity >> 1)intoldCapacity=elementData.length;intnewCapacity=oldCapacity+(oldCapacity>>1);if(newCapacity-minCapacity<0)newCapacity=minCapacity;if(newCapacity-MAX_ARRAY_SIZE>0)newCapacity=hugeCapacity(minCapacity);// minCapacity is usually close to size, so this is a win:elementData=Arrays.copyOf(elementData,newCapacity);//Notice that ```Arrays.copyOf``` is the core function and it has big performance influence on ArrayList!}

And then another question, how Arrays.copyOf is implemented?
First, from Arrays:

Sorry, guys, this is a JVM implemented method, so we can’t dive deeper, but I guess this method will finally invoke the memory copy system calls provided by OS.
Now, we come to our conclusion:

The key to understand and implement ArrayList is System.arraycopy(Object srcArray, Object destArray...), and everytime when the array space is not enough, we need to create a new array and call System.arraycopy. So if we know the final size, we should call ArrayList(int initialCapacity) to avoid unnecessary arraycopys.

We can see that the logic is quite simple campared to ArrayList. It just new a new Node then add the Node to the last of the list.

Add() mthod Benchmark time

We can already guess that the performance of the add method in LinkedList depends on new Node<>(l, e, null), and ArrayList depends on System.arraycopy(), which one will win? That’s do some simple tests.

We can see that the add() method of ArrayList outperforms LinkedList, and why the performance gap wider when size grows? Because the number of arraycopy operations grow more slowly. The default capacity is 10:

private static final int DEFAULT_CAPACITY = 10;

And then the capacity grows by 1.5x times:

int newCapacity = oldCapacity + (oldCapacity >> 1);

We can also write some simple code to calculate how many array copy operations needed when the size grows: