【问题标题】:How does 'Collections.sort()' use the result of the 'compare()' method?'Collections.sort()' 如何使用 'compare()' 方法的结果?
【发布时间】:2014-08-13 22:43:16
【问题描述】:

Comparator 接口中 compare() 方法的输出是 -1,0 或 1。然后将其传递给 Collections.sort() 方法,该方法可用于以自定义方式对列表进行排序。

sort() 对 compare() 方法的结果做了什么? (-1,0 或 1)

我认为我最困惑的是 compare() 有三个输出 负、正或 0)。但是为什么算法不只需要其中两个呢?不能 a=b 时的动作与 a>b 或 a

例如。比较两个数字 a 和 b,如果 ab 则取 b(compare() 返回 +1)。为什么算法需要区分 a

例如。

class ReverseAlphabeticalComparator implements Comparator<Integer> {

@Override
public int compare(Integer i1, Integer i2) {
    if(i1 > i2) {
        return 1;
    }
    else if(i1 < i2) {
        return -1;
    }

    return 0;
}  

class App {
public static void main(String[] args) {

    List<Integer> animals = new ArrayList<Integer>();
    animals.add(6);
    animals.add(2);
    animals.add(4);
    animals.add(7);
    animals.add(8);
    animals.add(3);

    Collections.sort(numbers, new ReverseNumericalComparator());

        for(String numbers: numbers) {
            System.out.println(numbers); //Prints numbers in reverse eg. 8,7,6,4,3,2
        }
    }
}

【问题讨论】:

  • 我建议您尝试研究如何为元素列表编写排序算法,只使用一种告诉您两个对象是否大于、小于或等于彼此的方法,然后你可以回答你自己的问题。 ;)

标签: java sorting collections compare comparator


【解决方案1】:

sort() 对 compare() 方法的结果做了什么?

sort 比较一系列元素对,并根据compare 的结果查看该对中的元素是否应该交换。

compare 的结果也不一定是-1 01。来自documentation

返回 negative 整数、zeropositive 整数,因为第一个参数
小于等于或大于第二个。

【讨论】:

    【解决方案2】:

    大多数(全部?)排序算法只需要知道对于我们正在排序的集合中的每个元素,a 是否更小/更大/等于b。因此,您只需从 compare() 返回一个负值、0 或正值(在许多情况下为 -1、0 和 1)。

    如果您阅读过不同的排序算法,您会注意到它们是建立在此之上的,从简单的冒泡排序到快速排序、归并排序等等。

    【讨论】:

    • 比较算法是所有排序算法的真子集。它们具有可证明的最小渐近复杂度 nlogn。还有其他非比较排序算法具有更好的渐近复杂性,例如计数排序。但是,这些比 nlogn 更快的非比较算法有一些注意事项,例如要求您了解数据的分布(桶排序)或复杂性随数据中的位数线性缩放(基数排序)。我们使用比较排序是因为它没有这些问题,而且在许多情况下,nlogn 几乎和 n 一样好。
    • 感谢您的回答。我正在编辑我的问题,以更全面地解释我对什么感到困惑
    【解决方案3】:

    这就是它的作用(Collections.sort 调用 Arrays.sort,后者调用 Arrays.mergeSort):

    private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low, int high, int off,
                                  Comparator c) {
    
        int length = high - low;
    
        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low && c.compare(dest[j-1], dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }
    
        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
    
        mergeSort(dest, src, low, mid, -off, c);
        mergeSort(dest, src, mid, high, -off, c);
    
        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (c.compare(src[mid-1], src[mid]) <= 0) {
           System.arraycopy(src, low, dest, destLow, length);
           return;
        }
    
        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && c.compare(src[p], src[q]) <= 0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }
    

    【讨论】:

    • 我认为最近的实现使用 timsort 而不是标准的mergesort。编辑:啊,Java 7 使用 timsort 进行非原始排序。
    猜你喜欢
    • 1970-01-01
    • 2020-01-27
    • 2015-06-14
    • 2017-06-19
    • 1970-01-01
    • 1970-01-01
    • 2012-10-20
    • 2013-07-07
    • 1970-01-01
    相关资源
    最近更新 更多