Sortinghard5-8 years

`Arrays.sort` on an `int[]` and on an `Integer[]` use two different algorithms under the hood. What are they, why does Java make that split, and what production bug can result from assuming they behave the same way?

Primitives (int[]) get a dual-pivot quicksort: in-place, no extra memory, excellent cache behaviour, and unstable — but that's fine, because two ints with the same value are genuinely indistinguishable, so there's no order between equal elements to preserve. Objects (Integer[], List<T>, anything sorted with a Comparator) get TimSort instead, which allocates temporary space but is stable — equal elements keep the relative order they had before sorting. That matters for objects because two records can compare equal on the field you sorted by while still differing in other fields, and code frequently relies on that: sorting a list by name and then re-sorting it by department, expecting names to stay ordered within each department, only works because the second sort is stable. Assuming an object sort behaves like a primitive sort — or hand-rolling a faster in-place sort for objects "for speed" — silently breaks that guarantee, and it tends to surface specifically on inputs with many ties, which test data with distinct, hand-picked values rarely has.

The lesson behind it →