如何使用自定义比较器对int数组进行排序?

Ale*_*dru 61 java sorting

我需要排序使用自定义比较int数组,但Java的库不为整数提供一种功能与比较器(比较器只能与对象一起使用).有没有简单的方法来做到这一点?

Jon*_*man 49

如果您无法更改输入数组的类型,则以下内容将起作用:

final int[] data = new int[] { 5, 4, 2, 1, 3 };
final Integer[] sorted = ArrayUtils.toObject(data);
Arrays.sort(sorted, new Comparator<Integer>() {
    public int compare(Integer o1, Integer o2) {
        // Intentional: Reverse order for this demo
        return o2.compareTo(o1);
    }
});
System.arraycopy(ArrayUtils.toPrimitive(sorted), 0, data, 0, sorted.length);
Run Code Online (Sandbox Code Playgroud)

这使用ArrayUtilscommons-lang项目轻松转换int[]Integer[],创建数组的副本,进行排序,然后将排序后的数据复制到原始数据上.

  • `return o2.compareTo(o1);`这是正确的吗?我相信这种方式会像我们预期的那样逆转...... (4认同)
  • 为什么不使用Arrays.sort而不是转换array-&gt; list-&gt; array? (2认同)

use*_*782 21

如何使用流(Java 8)?

int[] ia = {99, 11, 7, 21, 4, 2};
ia = Arrays.stream(ia).
    boxed().
    sorted((a, b) -> b.compareTo(a)). // sort descending
    mapToInt(i -> i).
    toArray();
Run Code Online (Sandbox Code Playgroud)

或就地:

int[] ia = {99, 11, 7, 21, 4, 2};
System.arraycopy(
        Arrays.stream(ia).
            boxed().
            sorted((a, b) -> b.compareTo(a)). // sort descending
            mapToInt(i -> i).
            toArray(),
        0,
        ia,
        0,
        ia.length
    );
Run Code Online (Sandbox Code Playgroud)

  • 不要使用`(a,b) - > b - a`作逆序.这个比较器可以溢出.注意`Comparator.reverseOrder()`的存在...... (5认同)
  • 我不知道我们不能在IntStream上排序(IntComparator). (4认同)
  • 完全错过了潜在的溢出。改编了答案。谢谢霍尔格! (2认同)

lev*_*tov 8

您可以IntArrays.quickSort(array, comparator)从 fastutil 库中使用。


小智 7

您不需要外部库:

Integer[] input = Arrays.stream(arr).boxed().toArray(Integer[]::new);
Arrays.sort(input, (a, b) -> b - a); // reverse order
return Arrays.stream(input).mapToInt(Integer::intValue).toArray();
Run Code Online (Sandbox Code Playgroud)

  • 引用[霍尔格斯对另一个答案的评论](/sf/ask/258939901/#comment63804518_33045466):“唐” t 使用 `(a, b) -&gt; b - a` 进行逆序。该比较器可能会溢出。注意 `Comparator.reverseOrder()` 的存在” (4认同)

小智 5

如果您不想复制数组(例如,数组很大),则可能需要创建一个List<Integer>可以用于排序的包装器:

final int[] elements = {1, 2, 3, 4};
List<Integer> wrapper = new AbstractList<Integer>() {

        @Override
        public Integer get(int index) {
            return elements[index];
        }

        @Override
        public int size() {
            return elements.length;
        }

        @Override
        public Integer set(int index, Integer element) {
            int v = elements[index];
            elements[index] = element;
            return v;
        }

    };
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用自定义比较器对此包装器列表进行排序。

  • @OB1:它看起来很整洁,但标准的`sort` 实现将整个列表复制到一个数组中,对其进行排序并将其写回。由于这个列表没有实现 `RandomAccess` 标记,回写将使用 `ListIterator` 而不是仅仅调用 `set`。 (3认同)