Сортировка массива 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();
}