Từ Java 7, Collections.sort và Arrays.sort (với object) dùng TimSort. Thuật toán này giả định comparator nhất quán, và khi trộn các run nó phát hiện được dữ liệu mâu thuẫn với giả định đó → ném IllegalArgumentException. Nghĩa là comparator của bạn vi phạm hợp đồng: phản đối xứng (sgn(compare(a,b)) == -sgn(compare(b,a))), bắc cầu, và nhất quán khi compare(a,b) == 0.
Bốn nguyên nhân hay gặp:
// 1. Tràn số khi trừ int
(a, b) -> a.value - b.value; // sai với giá trị lớn/âm
(a, b) -> Integer.compare(a.value, b.value); // đúng
// 2. Trả 1/-1 tùy tiện, không có nhánh bằng nhau
(a, b) -> a.score > b.score ? 1 : -1; // compare(x, x) trả -1 -> phá đối xứng
// 3. So sánh double bằng phép trừ, dính NaN hoặc mất chính xác
(a, b) -> (int) (a.price - b.price); // 0.5 bị cắt thành 0
// 4. Comparator dựa trên field bị thread khác sửa trong lúc sortCách sửa: dùng Integer.compare / Double.compare / Comparator.comparing(...).thenComparing(...), và chụp snapshot dữ liệu trước khi sort nếu nó có thể thay đổi.
Cờ -Djava.util.Arrays.useLegacyMergeSort=true chỉ tắt việc kiểm tra chứ không sửa comparator sai — kết quả sắp xếp vẫn không xác định, nên đừng coi đó là giải pháp.