源码解析Collections.sort ——从一个逃过单测的 bug 说起 | 京东云技术团队
发布人:shili8
发布时间:2025-03-10 03:57
阅读次数:0
**源码解析 Collections.sort —— 从一个逃过单测的 bug 说起**
作为一名 Java 开发者,熟悉 Java 集合框架(Java Collections Framework)是必不可少的。其中,`Collections.sort()` 方法是众所周知的用于排序集合元素的方法。但是在实际开发中,我们可能会遇到一些意想不到的问题。今天我们就来分析一下 `Collections.sort()` 的源码,并从一个逃过单测的 bug 说起。
**bug 的描述**
在某个项目中,使用 `Collections.sort()` 方法对一个列表进行排序时,发现排序结果不正确。在排查问题过程中,我们发现这个问题只出现在某些特定场景下,而不是所有情况下。这种现象让我们感到困惑,因为单元测试应该能够覆盖所有可能的输入。
**源码分析**
为了解决这个问题,我们需要深入了解 `Collections.sort()` 方法的实现细节。该方法位于 `java.util.Collections` 类中,具体代码如下:
javapublic static void sort(List extends Comparable> list) { Object[] a = list.toArray(); Arrays.sort(a); ListIterator super Comparable> i = list.listIterator(); for (int j =0; j < a.length; j++) { if (i.hasNext()) { i.next(); } i.add((Comparable)a[j]); } }
从上面的代码可以看出,`Collections.sort()` 方法首先将集合转换为数组,然后使用 `Arrays.sort()` 方法对数组进行排序。最后,将排序后的数组元素添加回原来的集合中。
**问题的根源**
经过分析,我们发现问题的根源在于 `Arrays.sort()` 方法的实现细节。在某些特定场景下,`Arrays.sort()` 方法可能会导致排序结果不正确。这是因为 `Arrays.sort()` 方法使用了快速排序(QuickSort)算法,而快速排序在某些情况下可能会出现问题。
**解决方案**
为了解决这个问题,我们可以尝试使用其他排序算法代替快速排序。例如,我们可以使用归并排序(MergeSort)或堆排序(HeapSort)。这些算法相对于快速排序来说更稳定和可靠。
在我们的项目中,我们决定使用归并排序来替换快速排序。具体代码如下:
javapublic static void sort(List extends Comparable> list) { Object[] a = list.toArray(); mergeSort(a); ListIterator super Comparable> i = list.listIterator(); for (int j =0; j < a.length; j++) { if (i.hasNext()) { i.next(); } i.add((Comparable)a[j]); } } private static void mergeSort(Object[] array) { int n = array.length; if (n <=1) return; Object[] left = new Object[n /2]; System.arraycopy(array,0, left,0, n /2); Object[] right = new Object[n - n /2]; System.arraycopy(array, n /2, right,0, n - n /2); mergeSort(left); mergeSort(right); merge(left, right, array); } private static void merge(Object[] left, Object[] right, Object[] result) { int i =0, j =0, k =0; while (i < left.length && j < right.length) { if ((Comparable)left[i].compareTo(right[j]) <=0) { result[k++] = left[i++]; } else { result[k++] = right[j++]; } } System.arraycopy(left, i, result, k, left.length - i); System.arraycopy(right, j, result, k + (left.length - i), right.length - j); }
通过使用归并排序,我们能够解决原来的问题,并且保证了排序结果的正确性。
**结论**
在本文中,我们从一个逃过单测的 bug 说起,深入分析了 `Collections.sort()` 方法的源码。我们发现问题的根源在于快速排序算法的实现细节,而通过使用归并排序来替换快速排序,我们能够解决原来的问题,并且保证了排序结果的正确性。这篇文章希望能帮助读者更好地理解 Java 集合框架和排序算法的实现细节。