Сортировка массива Java по своим правилам методом `Arrays.sort()`

Сортировка массива Java по своим правилам методом `Arrays.sort()`


Java. Имеется массив int{0, -14, 191, 161, 19, 144, 195, 1}.

Хочется, используя метод Arrays.sort(), отсортировать массив по абсолютному значению, возможно ли это сделать с помощью компаратора?



Сортировка массивов при помощи компаратора НЕ доступна для массивов примитивных типов int[]long[]double[] и т.д., поэтому для кастомной сортировки придётся преобразовать массив либо в список List<Integer> либо в массив Integer[], отсортировать его при помощи метода Arrays.sort(T[] arr, Comparator<? super T>) c, и затем преобразовать обратно в массив примитивов.

При этом вместо компаратора следует передавать функцию для конвертации Integer в примитив, на основании которой можно построить компаратор при помощи Comparator.comparingInt(ToIntFunction<? super T>) fn.

public static void sortIntArray(int[] arr, ToIntFunction<Integer> c) {
    Integer[] ints = new Integer[arr.length];
    Arrays.setAll(ints, i -> arr[i]);
    Arrays.sort(ints, Comparator.comparingInt(c));
    Arrays.setAll(arr, i -> ints[i]);
}

Также можно использовать Stream API и возвращать новый отсортированный массив, однако следует учесть, что IntStream также не поддерживает кастомную сортировку, и придется преобразовать его в Stream<Integer> и затем обратно при помощи Stream::mapToInt:

public static int[] sortInts(int[] arr, ToIntFunction<Integer> c) {
    return Arrays.stream(arr)                // IntStream
        .boxed()                             // Stream<Integer>
        .sorted(Comparator.comparingInt(c))  // Stream<Integer>
        .mapToInt(Integer::intValue)         // IntStream
        .toArray();                          // int[]
}

Тест:

int[] arr = {0, -14, 191, 161, 19, 144, 195, 1};
sortIntArray(arr, Math::abs);
// или arr = sortInts(arr, Math::abs);
System.out.println(Arrays.toString(arr));

Вывод:

[0, 1, -14, 19, 144, 161, 191, 195]

Аналогично, в метод для кастомной сортировки можно передавать IntUnaryOperator, принимающий и отдающий результат типа int, тогда при вызове компаратора нужно будет передать ссылку на соответствующий метод IntUnaryOperator::applyAsInt:

public static int[] sortInts(IntUnaryOperator fun, int... arr) {    
    return Arrays.stream(arr)
        .boxed()
        .sorted(Comparator.comparingInt(fun::applyAsInt))
        // аналогия с явным анбоксингом
        // .sorted(Comparator.comparingInt(i -> fun.applyAsInt(i.intValue())))
        .mapToInt(Integer::intValue)
        .toArray();
}



Report Page