I'm improving the quality of sorting tests as a part of PR
https://github.com/openjdk/jdk/pull/27411 and found a bug in parallel sorting.
According to the javadoc object sorting Arrays.sort() and Arrays.parallelSort()
are _stable_ (keep the order of the elements with the same key), but a simple
test shows that parallel sort of objects doesn't work correctly, see the test:
import java.util.Arrays;
import java.util.Comparator;
public class ParallelStabilityTest {
private static final int LENGTH = 16_385;
public static void main(String[] args) {
Pair[] a = new Pair[LENGTH];
for (int i = 0; i < LENGTH; ++i) {
a[i] = new Pair(1, i);
}
Arrays.parallelSort(a); // failed
// Arrays.parallelSort(a, byKey); // failed
// Arrays.sort(a); // ok
// Arrays.sort(a, byKey); // ok
checkStability(a);
System.out.println("PASSED");
}
record Pair(int key, int index) implements Comparable<Pair> {
@Override
public int compareTo(Pair p) {
return Integer.compare(key , p.key);
}
@Override
public String toString() {
return "[" + key + ", " + index + "]";
}
}
private static final Comparator<Pair> byKey =
Comparator.comparingInt(Pair::key);
private static void checkStability(Pair[] a) {
for (int i = 1; i < a.length; ++i) {
if (a[i - 1].key == a[i].key && a[i - 1].index > a[i].index) {
System.out.println("FAILED: not stable at i = " + i + ": " +
a[i - 1] + " and " + a[i]);
System.exit(1);
}
}
}
}
The root of the problem actually is not in parallelism, but in the algorithm of
part merging. We split larger and find point in smaller in method
Merger.compute() from class ArraysParallelSortHelpers, but if we have parts of
equal elements, it doesn't work correctly, comparison in `else` branch must be
strong (`<`). The fix is very simple: `<=` -> `<`.
---------
- [x] I confirm that I make this contribution in accordance with the [OpenJDK
Interim AI Policy](https://openjdk.org/legal/ai).
-------------
Commit messages:
- JDK-8393047: Arrays.parallelSort sorting of objects is not stable: updated
year: 2026
- JDK-8393047: Arrays.parallelSort sorting of objects is not stable
Changes: https://git.openjdk.org/jdk/pull/33190/files
Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=33190&range=00
Issue: https://bugs.openjdk.org/browse/JDK-8393047
Stats: 62 lines in 2 files changed: 38 ins; 6 del; 18 mod
Patch: https://git.openjdk.org/jdk/pull/33190.diff
Fetch: git fetch https://git.openjdk.org/jdk.git pull/33190/head:pull/33190
PR: https://git.openjdk.org/jdk/pull/33190