Menu

LinkedHashMap is always better than HashMap

Deterministic code is much easier to debug & understand than non-determinstic code. Got a test that’s failing? Launch the debugger, step through the code, and find the exact statement where an assumption is violated. For me this often looks like a binary search. I add breakpoints and make assertions like “everything is fine before we call pruneCache()”. I’ll run the app, learn something, and repeat.

When you use HashMap in your programs, you’re introducing needless nondeterminism. This is because HashMap’s iteration order is different between platforms (Android vs. Java) and between executions for classes that don’t override equals() and hashCode().

This nondeterminism is toxic to debugging. I think it’s even worse than the nondeterminism caused by multithreading because it’s so unexpected.

Does this program always return the same result?

private static float massPerUnit(  
    float totalMass, float w, float h, float d) {
  Map<CharSequence, Float> dimensions = new HashMap<>();
  dimensions.put(dimension("width", "x"), w);
  dimensions.put(dimension("height", "y"), h);
  dimensions.put(dimension("depth", "z"), d);

  float massPerUnit = totalMass;
  for (Float dimension : dimensions.values()) {
    massPerUnit /= dimension;
  }

  return massPerUnit;
}

Surprise, it doesn’t. And HashMap’s non-deterministic iteration order is to blame.

LinkedHashMap is great. It’s just as easy-to-use as HashMap, and the runtime cost is negligible. Most of the performance & memory cost of HashMap is in allocating and managing its hash entries, and LinkedHashMap uses the same entries, just with extra next and previous links.

If you’re writing Java code, always prefer LinkedHashMap over HashMap. Even if you aren’t iterating the collection, it’s one less thing that can go wrong.