[Note] This article is translated from: Java ArrayList vs LinkedList | Baeldung
1 Overview
For collections, the Java standard library provides a large number of options to choose from. Among these options, there are two well-known List , called ArrayList and LinkedList , each of which has its own properties and use cases.
In this tutorial, we will see how these two are achieved. Then, we will evaluate the differences in each application.
2. ArrayList
Internally, the ArrayList uses an array to implement the List interface . Since the array is of fixed size in Java, ArrayList creates an array with some initial capacity. During this process, if we need to store more items than the default capacity, it will replace the array with a new, larger array.
In order to better understand its properties, let us evaluate this data structure based on its three main operations: adding items, getting items by index, and deleting items by index.
2.1. Add
When we create an empty ArrayList , it will initialize its backing array with the default capacity (currently 10):
Adding a new item when the array is not full is as simple as assigning the item to a specific array index. This array index is determined by the current array size, because we are actually appending to the list:
backingArray[size] = newItem;
size++;
Therefore, in the best and general case, the time complexity of the addition operation is O(1) , which is very fast. However, as the backing array becomes full, the efficiency of adding implementations will decrease:
To add new items, we should first initialize a new array with a larger capacity and copy all existing items to the new array . Only after copying the current element, we can add a new item. Therefore, in the worst case, the time complexity is O(n), because we have to copy n elements first.
In theory, the running time of adding new elements is the amortization constant . In other words, it takes O(n) time to add n elements. However, due to replication overhead, some single additions may perform poorly.
2.2. Access by index
Accessing items by index is the real highlight ArrayList To retrieve subscript i term, we need only return to the reserve located on the array i an indexed item. Therefore, through index operation is always O(1) .
2.3. Delete by index
Suppose we want ArrayList , which corresponds to element 15 in our backing array:
After marking the desired element as deleted, we should move all the following elements back by one index. Obviously, the closer the element is to the beginning of the array, the more elements we should move . Therefore, the time complexity is O(1) in the best case and O(n) in the average and worst case.
2.4. Application and Restrictions
Generally, when List implement, ArrayList is the default choice of many developers. In fact, when the number of reads far exceeds the number of writes, this is actually a wise choice .
Sometimes we need to read and write equally frequently. If we do estimate the maximum number of possible items, then it still makes sense to use ArrayList . If this is the case, we can initialize the ArrayList with the initial capacity:
int possibleUpperBound = 10_000;
List<String> items = new ArrayList<>(possibleUpperBound);
This estimation can prevent a lot of unnecessary copying and array allocation.
In addition, the array is indexed by int values in Java. Therefore, it is impossible to store more than 2 to the 32th power in a Java array. Therefore, the same is true in ArrayList .
3. LinkedList
LinkedList, as the name suggests, uses a collection of linked nodes to store and retrieve elements . For example, here is the Java implementation after adding four elements:
Each node maintains two pointers: one points to the next element, and the other points to the previous element. To extend this, the doubly linked list has two pointers to the first and last items.
Again, let us evaluate this implementation based on the same basic operations.
3.1. Add
In order to add a new node, first, we should link the current last node to the new node:
Then update the last pointer:
Because these two operations are very simple, the time complexity of the addition operation is always O(1) .
3.2. Access by index
LinkedList is different from ArrayList and does not support fast random access. Therefore, in order to find elements by index, we should manually traverse some parts of the list .
In the best case, when the requested item is near the beginning or end of the list, the time complexity will be as fast as O(1) However, in the average and worst case, we might end up with O(n) because we have to check many nodes one by one.
3.3. Delete by index
In order to delete an item, we should first find the requested item, and then unlink it from the list . Therefore, the access time determines the time complexity—that is, O(1) in the best case, and O(n) in the average and worst case.
3.4. Application
When the adding rate is much higher than the reading rate, LinkedLists more suitable.
In addition, when most of the time we want the first or last element, it can be used to read dense scenes. It is worth mentioning that LinkedList also implements the Deque interface-supporting efficient access to both ends of the collection.
Usually, if we know their implementation differences, then we can easily choose one for a specific use case.
For example, suppose we will store a large number of time series events in a list-like data structure. We know that we receive emergencies every second.
In addition, we need to regularly check all events and provide some statistics. For this use case, LinkedList is a better choice because the adding rate is much higher than the reading rate.
In addition, we read all items, so we cannot exceed the upper limit of O(n)
4 Conclusion
In this tutorial, we first deeply studied how ArrayList and LinkLists are implemented in Java.
We also evaluated different use cases for each of them.
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。