Running on Java 26+35-2893 (Preview)
Home of The JavaSpecialists' Newsletter

334ArrayList vs LinkedList Puzzle

Author: Dr Heinz M. KabutzDate: 2026-04-28Java Version: 25Sources on GitHubCategory: Performance
 

Abstract: Every schoolboy knows that arrays are faster than linked structures, no matter the language. In this newsletter we present a puzzle where we find LinkedList outperforming ArrayList for ZGC. Let's see who comes up with the most thorough explanation why.

 

Welcome to the 334th edition of The Java(tm) Specialists' Newsletter. In May 2026 I am speaking at the JNation Conference in Coimbra, Portugal. It is my first visit to Portugal, and I'm very excited. I was supposed to go last year, but had to cancel last minute. JNation is sold out for 2026, so be sure to grab a seat for 2027 as soon as it opens up. The speaker lineup looks amazing, with 1/4 Java Champions! I will also be speaking at the Lisbon JUG.

javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.

ArrayList vs LinkedList Puzzle

By now, I hope that you have learned to never use LinkedList. Even the author of the class famously tweeted that he never uses it. Since Q3 last year, requests for the Java 25 version of my "Extreme Java - Concurrency Performance Courses" have steadily increased. We had an amazing in-house class last week, with excellent engineers and insightful questions. Towards the end of the course, when we were looking at performance, someone asked about LinkedList. I wrote a quick demo that showed how long it would take to insert 100m elements into ArrayList vs LinkedList. It was not meant to be a thorough benchmark, just something hacked together on the fly to quickly answer a question. It looked somewhat like this:

import java.lang.management.ManagementFactory;
import java.util.*;
import java.util.function.*;

public abstract class ListPuzzle {
    void run(Supplier<? extends List<Integer>> supplier) {
        var tmb = ManagementFactory.getThreadMXBean();
        var tim = System.nanoTime();
        var cpu = tmb.getCurrentThreadCpuTime();
        var usr = tmb.getCurrentThreadUserTime();
        try {
            var list = supplier.get();
            System.out.println(list.getClass() + ":");
            for (var i = 0; i < 100_000_000; i++) {
                list.add(42);
            }
        } finally {
            tim = System.nanoTime() - tim;
            usr = tmb.getCurrentThreadUserTime() - usr;
            cpu = tmb.getCurrentThreadCpuTime() - cpu;
            System.out.printf("tim=%d,", (tim / 1000000));
            System.out.printf("cpu=%d,", (cpu / 1000000));
            System.out.printf("usr=%d%n", (usr / 1000000));
        }
    }
}

For ArrayList, we have a simple subclass:

public class ArrayListPuzzle extends ListPuzzle {
    void main() {
        run(java.util.ArrayList::new);
    }
}

Similarly, for LinkedList:

public class LinkedListPuzzle extends ListPuzzle {
    void main() {
        run(java.util.LinkedList::new);
    }
}

I asked Claude Opus 4.7 which would be faster, and it said "ArrayList - by a wide margin." And this is also what we expected to see. Running Java 25.0.2+10 Amazon Corretto on my MacBookPro M2 Max, with 12 cores (8 performance and 4 efficiency cores) and 96 GB of memory, I see the following results:

class java.util.LinkedList:
tim=3205,cpu=382,usr=348
class java.util.ArrayList:
tim=439,cpu=363,usr=312

Note that tim is the elapsed time, which we also call "wall clock time". That is the time that we would see on our stopwatch if we measured how long it takes to run the code. Then cpu is how much CPU time is burned. For a CPU intensive task, we would expect this to be similar to the elapsed time. Lastely we see the usr representing user time, of actual work done, as opposed to waiting for system time wasted on voluntary context switches and the like. We see clearly that ArrayList is 7.3x "faster" than LinkedList in terms of elapsed time. However, when we look at the user time, ArrayList is only 1.12x "faster".

There are good reasons for the differences, and also why this is a flawed demo.

We can also see how this runs with ZGC:

class java.util.LinkedList:
tim=548,cpu=547,usr=374
class java.util.ArrayList:
tim=686,cpu=686,usr=582

Hmmm, that's interesting. We now see that the LinkedList is now 1.25x faster with elapsed time and 1.56x faster with user time! What gives?

Let's have some fun. There are quite a few different things going on here. Whoever sends me the most thorough explanation gets their name forever immortalized in the next edition of The Java(tm) Specialists' Newsletter. You may gladly use whatever AI tool you like, but please let us know which one(s) you used. Hint: There are quite a few factors in play.

Kind regards

Heinz

 

Comments

We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)

When you load these comments, you'll be connected to Disqus. Privacy Statement.

Related Articles

Browse the Newsletter Archive

About the Author

Heinz Kabutz Java Conference Speaker

Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Superpack

Java Specialists Superpack Our entire Java Specialists Training in one huge bundle more...

Free Java Book

Dynamic Proxies in Java Book
Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

We can help make your Java application run faster and trouble-shoot concurrency and performance bugs...