Mac
Mac

Reputation: 1495

HashMap or TreeMap or LinkedHashMap which one is fastest to iterate over?

I have a Map which is filled up during the start up of application. It doesn't change later during the execution of application. Later this map is only used to iterate all the elements in it. Which concrete implementation of Map should I choose? HashMap or TreeMap or LinkedHashMap ?
UPDATE
Insertion order doesn't matter. The only thing that matters is fast iteration of all elements (say 6000 elements).

Upvotes: 20

Views: 32598

Answers (7)

Marko Topolnik
Marko Topolnik

Reputation: 200138

None of the other answers here take into consideration the effects of the CPU cache, which can be huge when iteration is concerned.

One way to improve this is to use just a single array of interleaved keys and values (keys at even indices, values at odd ones). This will tightly group together these data items and maximally leverage the cache, at least for the references.

But the true, screaming improvement would be achieved if you could avoid creating objects which hold your data and use just arrays of primitive values. This is, naturally, highly dependent on your use case.

Upvotes: 11

jippiee
jippiee

Reputation: 85

As of Java 10 you can use one of the Map.of() overloaded methods or Map.copyOf() to create an unmodifiable Map. As the map returned by these methods doesn't support putting any new entries into the map, the existing keys/values are stored in an interleaving pattern as described in this answer. This should offer the best performance for your use case.

Upvotes: 1

Zim-Zam O'Pootertoot
Zim-Zam O'Pootertoot

Reputation: 18148

HashMap will generally be fastest, since it has the best cache behavior (HashMap iterates directly over the backing array, whereas TreeMap and LinkedHashMap iterate over linked data structures).

You may want to use an ImmutableMap or UnmodifiableMap if the map isn't going to change once it's initialized

Upvotes: 13

hamom1968
hamom1968

Reputation: 1

The Map.forEach(BiConsumer) is almost always faster than Iterators, sometimes by a large margin. If you were summing the values for example:

public class TestForStackOverflow {
    int sum = 0;

    // Or whatever Map you are using
    Map<Object, Integer> map = new HashMap();

    static class C implements BiConsumer<Object, Integer> {
        int sum = 0;

        @Override
        public void accept(Object k, Integer v) {
            sum += v;
        }
    }

    public int getSum(Map map) {
        C c = new C();
        map.forEach(c);
        return c.sum;
    }

    public int getSum2(Map map) {
        map.forEach((k, v) -> sum += v);
        return sum;
    }
}

Upvotes: -2

OldCurmudgeon
OldCurmudgeon

Reputation: 65793

I wouldn't use the map. If all you want is to iterate through the entries make a new ArrayList of what you need and use that - you cannot get faster than an ArrayList for iteration.

// Which map you use only chooses the order of the list.
Map<Key,Value> map = new HashMap<>();
// The list to iterate for maximum speed.
List<Map.Entry<Key,Value>> list = new ArrayList<>(map.entrySet());

This way you iterate across the entry set just once to build the list. From then on you are iterating across the list again and again - which certainly should be close to optimal.

Note Changed from LinkedList to ArrayList on Marko's suggestion.

Upvotes: 8

&#211;scar L&#243;pez
&#211;scar L&#243;pez

Reputation: 235984

I agree with Zim-Zam's answer, and add something: if you need to access both the keys and the values during the iteration, the fastest way is using the entrySet() method, as discussed here.

Now, if you're sure that the map is never going to change, why not use a separate data structure for iteration? for example: iterate once over the finished map and fill with its contents a couple of arrays, one with the keys and the other with the values, in the same corresponding positions. Then traversing those arrays will be as fast as it can get.

Upvotes: 1

Evgeniy Dorofeev
Evgeniy Dorofeev

Reputation: 135992

If your map is used only to iterate over elements and the speed of iteration is important, then convert the map into an ArrayList and iterate over it, this will be the fastest way.

Upvotes: 3

Related Questions