Java Clean Architecture Masterclass

Java Clean Architecture MasterclassNov 20-21

Join

Common

Maven Central Build Status Coverage License javadoc

Commonly usable classes without dependencies.

org.int4.common.collection.ShiftList

ShiftList is a high-performance, general-purpose List and Deque implementation optimized for use cases where frequent insertions and removals occur near the head or tail of the list. It combines the performance benefits of block-based storage with a rotating offset mechanism to avoid costly element shifts typical of ArrayList.

Why ShiftList?

Standard Java collections like ArrayList and LinkedList trade off insertion/removal speed, memory locality, and access time:

Key Design Concepts

Benchmark Summary

All benchmarks were performed using JMH. For raw data see the benchmarks folder. The lists compared are JDK's ArrayList, LinkedList, and Apache Commons Collections' TreeList.

add(int) Benchmark get(int) Benchmark

Insertions and removals

Measurements were done performing exactly 10,000 operations per iteration. For smaller lists, several lists were used to not exceed 0.5 * size elements added per list. The resuls are in nano seconds per element. Bolded results are fastest or within 10% of fastest.

Operation Size ShiftList ArrayList LinkedList TreeList
Add First 1,000 2.4 ns 54.8 ns 2.3 ns 57.2 ns
Add First 100,000 2.4 ns 3,656.5 ns 1.8 ns 107.9 ns
Add First 10,000,000 3.5 ns (*) - 3.8 ns 134.1 ns
Add Last 1,000 2.2 ns 2.6 ns 2.3 ns 54.5 ns
Add Last 100,000 2.3 ns (**) 5.0 ns 1.8 ns 97.0 ns
Add Last 10,000,000 3.7 ns 3.9 ns 3.9 ns 140.0 ns
Add Random 1,000 32.4 ns 40.5 ns 364.5 ns 60.7 ns
Add Random 100,000 80.6 ns 1,905.4 ns 34,570.5 ns 284.7 ns
Add Random 10,000,000 1,263.7 ns 419,777.2 ns (*) - 1,517.1 ns
Remove First 1,000 1.8 ns 38.7 ns 1.7 ns 34.8 ns
Remove First 100,000 1.7 ns 3,191.3 ns 1.8 ns 99.0 ns
Remove First 10,000,000 2.3 ns (*) - 2.6 ns 113.7 ns
Remove Last 1,000 1.6 ns 0.3 ns 1.7 ns 36.9 ns
Remove Last 100,000 1.6 ns 0.6 ns 1.7 ns 84.7 ns
Remove Last 10,000,000 2.2 ns 1.1 ns 2.0 ns 140.0 ns
Remove Random 1,000 24.8 ns 29.0 ns 164.0 ns 50.2 ns
Remove Random 100,000 94.4 ns 1,596.7 ns 25,125.0 ns 323.2 ns
Remove Random 10,000,000 1,923.8 ns 399,569.4 ns (*) - 1,423.9 ns

(*) Timed out (max 1 minute per test)
(**) ArrayList does a re-allocate at 106,710 elements which skewed these results a bit

Reading

Operation Size ShiftList ArrayList LinkedList TreeList
Get Random 1,000 1.1 ns 0.2 ns 243.6 ns 34.6 ns
Get Random 100,000 1.1 ns 0.4 ns 26,924.8 ns 121.9 ns
Get Random 10,000,000 2.3 ns 2.2 ns (*) - 658.8 ns
Get Sequential 1,000 0.7 ns 0.1 ns 228.0 ns 9.2 ns
Get Sequential 100,000 0.7 ns 0.1 ns 27,226.6 ns 37.6 ns
Get Sequential 10,000,000 0.7 ns 0.1 ns (*) - 43.6 ns

(*) Timed out (max 1 minute per test)

Time complexity

Operation ShiftList ArrayList LinkedList TreeList
Add/remove at tail O(1) O(1) O(1) O(log n)
Add/remove at head O(1) O(n) O(1) O(log n)
Random access O(1) O(1) O(n) O(log n)
Add/remove at index O(n/b) O(n) O(n) O(log n)

Where n is the number of elements the list holds, and b is the block size of ShiftList

ShiftList provides performance close to ArrayList for the common get(int) operation due to minimal indirection when locating an element. In contrast, LinkedList and TreeList require pointer traversal, which incurs higher actual latency than their asymptotic complexity suggests.

Feature ShiftList ArrayList LinkedList TreeList
Memory locality ++ ++ -- --
Estimated memory/element 4-8 bytes 4-6 bytes ~24 bytes ~32 bytes

LinkedList and TreeList allocate a wrapper object per element, leading to high memory overhead and poor memory locality due to non-contiguous storage. ShiftList stores elements in contiguous blocks, improving cache performance. Its capacity is always a power of two, and in the worst case (50% utilization), memory usage is approximately 8 bytes per element. By contrast, ArrayList typically grows by 50% when resizing and can trim to fit, leading to more compact memory usage when fully utilized.

Limitations

Join libs.tech

...and unlock some superpowers

GitHub

We won't share your data with anyone else.