Arrays.sort: примеры (JAVA)

Метод Arrays.sort() - назначение и варианты
Раздел: Массивы
Arrays.sort(int[] a): void

Описание и поведение

Метод Arrays.sort() из пакета java.util выполняет сортировку массивов на месте. Возвращаемого значения у метода нет (возвращает void); элементы исходного массива переупорядочиваются в порядке возрастания в соответствии с естественным порядком элементов или с указанным компаратором.

Основные варианты:

  • Arrays.sort(int[] a) и аналогичные перегрузки для byte, char, short, long, float, double: сортировка массивов примитивов.
  • Arrays.sort(Object[] a): сортировка массива объектов по их естественному порядку (элементы должны реализовывать Comparable).
  • Arrays.sort(T[] a, Comparator c): сортировка массива объектов с использованием переданного Comparator.
  • Для всех перечисленных перегрузок существуют варианты с диапазоном: Arrays.sort(a, fromIndex, toIndex). Индекс fromIndex включается, toIndex исключается.
  • С Java 8 добавлен Arrays.parallelSort(...) для параллельной сортировки больших массивов с использованием Fork/Join.

Поведение и характеристики:

  • Сортировка выполняется на месте - для примитивных и ссылочных массивов метод не возвращает новый массив.
  • Для массивов объектов сортировка стабильна (с Java 7 для объектов применяется адаптивный стабильный алгоритм, похожий на TimSort). Для примитивов используется быстрый алгоритм (двухопорный быстрая сортировка), который не гарантирует стабильность.
  • При отсутствии Comparator элементы объектов должны быть взаимно сопоставимы, иначе возникает ClassCastException.
  • Особые случаи для чисел: при сортировке float и double имеются особенности для NaN и знака нуля: порядок определяется спецификацией методов сравнения класса-обертки (Float.compare, Double.compare).

Основные исключения и возвраты:

  • Метод возвращает void. В случае некорректных входных данных бросаются исключения: NullPointerException при null вместо массива, ClassCastException при несравнимых объектах, IllegalArgumentException при некорректных границах диапазона (fromIndex > toIndex) и ArrayIndexOutOfBoundsException / IndexOutOfBoundsException при выходе индексов за пределы.

Короткие примеры использования

Сортировка массива примитивов

int[] a = {5, 3, 8, 1};
Arrays.sort(a);
System.out.println(Arrays.toString(a));
[1, 3, 5, 8]

Сортировка строк с компаратором (обратный порядок)

String[] s = {"beta", "alpha", "gamma"};
Arrays.sort(s, Comparator.reverseOrder());
System.out.println(Arrays.toString(s));
[gamma, beta, alpha]

Сортировка поддиапазона в массиве примитивов

int[] b = {5, 3, 8, 1, 2};
Arrays.sort(b, 1, 4); // сортируется только b[1..3]
System.out.println(Arrays.toString(b));
[5, 1, 3, 8, 2]

Сортировка объектов с естественным порядком

Integer[] nums = {4, 2, 7, 1};
Arrays.sort(nums);
System.out.println(Arrays.toString(nums));
[1, 2, 4, 7]

Параллельная сортировка (Java 8+)

long[] arr = {10, 3, 5, 1, 8};
Arrays.parallelSort(arr);
System.out.println(Arrays.toString(arr));
[1, 3, 5, 8, 10]

Аналоги в Java и особенности

  • Arrays.parallelSort() - предпочтительнее для очень больших массивов и многопроцессорных машин; использует параллельный алгоритм, накладные расходы на потоки могут не окупиться для небольших массивов.
  • Collections.sort(List<T> list) и List.sort(Comparator) - для списков; под капотом применяется тот же алгоритм, что и для массивов объектов (стабильный).
  • Stream.sorted() - возвращает упорядоченный поток; полезно для ленивых и цепочных преобразований, но создает новый поток значений, не сортирует существующий массив на месте.
  • Вспомогательные библиотеки: Guava, Apache Commons Collections предлагают утилиты для сортировок коллекций и потоков; используются при необходимости дополнительных удобств.

Аналоги в других языках

PHP

$a = [5, 3, 8, 1];
sort($a);
print_r($a);
Array ( [0] => 1 [1] => 3 [2] => 5 [3] => 8 )

JavaScript

let a = [5,3,8,1];
a.sort((x,y) => x - y);
console.log(a);
[1,3,5,8]

Python

a = [5,3,8,1]
a.sort()
print(a)
# или sorted(a) для нового списка
[1, 3, 5, 8]

SQL

SELECT * FROM table ORDER BY column ASC;

C#

int[] a = {5,3,8,1};
Array.Sort(a);
Console.WriteLine(string.Join(",", a));
1,3,5,8

Lua

local a = {5,3,8,1}
table.sort(a)
for i,v in ipairs(a) do print(v) end
1\n3\n5\n8

Go

a := []int{5,3,8,1}
sort.Ints(a)
fmt.Println(a)
[1 3 5 8]

Kotlin

val a = intArrayOf(5,3,8,1)
a.sort()
println(a.joinToString(","))
1,3,5,8

Отличия от Java: во многих языках сортировка возвращает новый массив/коллекцию (иммутабельные подходы), в Java Arrays.sort() сортирует на месте. В JavaScript по умолчанию sort() приводит элементы к строкам, поэтому для чисел рекомендуется передавать сравниватель.

Типичные ошибки и примеры

NullPointerException при null-массиве

int[] a = null;
Arrays.sort(a);
Exception in thread "main" java.lang.NullPointerException
	at java.util.Arrays.sort(Arrays.java:_____)

ClassCastException при несравнимых объектах

Object[] o = {"a", 1};
Arrays.sort(o);
Exception in thread "main" java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
	at java.util.ComparableTimSort.countRunAndMakeAscending(...)
	... 

IllegalArgumentException при неверных границах диапазона

int[] c = {1,2,3};
Arrays.sort(c, 2, 1); // fromIndex > toIndex
Exception in thread "main" java.lang.IllegalArgumentException: fromIndex(2) > toIndex(1)
	at java.util.Arrays.rangeCheck(...)
	... 

Ошибки при работе с NaN и знаковым нулем

double[] d = {Double.NaN, -0.0, 0.0, 1.0};
Arrays.sort(d);
System.out.println(Arrays.toString(d));
[-0.0, 0.0, 1.0, NaN]

Подробные различия зависят от реализации сравнения в типах-обертках.

Изменения в реализации в последних версиях Java

  • Java 7: для массивов объектов введен адаптивный стабильный алгоритм (TimSort-подобный), для массивов примитивов применена двухопорная быстрая сортировка (dual-pivot quicksort) - это улучшило производительность по сравнению с прежними реализациями.
  • Java 8: добавлен Arrays.parallelSort() - параллельная реализация, использующая Fork/Join.
  • Последующие релизы включали оптимизации производительности и исправления, API остался совместимым; семантика методов и исключения не изменилась существенно.

Расширенные и редкие примеры

Сортировка объектов с нестандартным порядком и null-значениями

Пример java
String[] names = {"Иван", null, "Анна", "Борис"};
Arrays.sort(names, Comparator.nullsFirst(String::compareTo));
System.out.println(Arrays.toString(names));
[null, Анна, Борис, Иван]

Стабильность сортировки объектов (пример)

Пример java
record Item(String key, int id) {}
Item[] items = {new Item("a",1), new Item("b",2), new Item("a",3)};
Arrays.sort(items, Comparator.comparing(Item::key));
for (Item it : items) System.out.println(it);
// Порядок элементов с одинаковым ключом сохраняется (стабильно)
Item[key=a, id=1]
Item[key=a, id=3]
Item[key=b, id=2]

Сортировка двумерного массива по первому столбцу

Пример java
int[][] mat = {{2,9},{1,7},{2,3}};
Arrays.sort(mat, Comparator.comparingInt(a -> a[0]));
System.out.println(Arrays.deepToString(mat));
[[1, 7], [2, 9], [2, 3]]

При равных первых элементах относительный порядок строк сохранится (стабильность).

Использование Collator для локализованной сортировки

Пример java
String[] ru = {"ёж", "ящик", "яблоко"};
Collator coll = Collator.getInstance(new Locale("ru"));
Arrays.sort(ru, coll);
System.out.println(Arrays.toString(ru));
[ёж, яблоко, ящик]  // пример порядка в зависимости от локали

Частичная сортировка для поиска k наименьших (простой подход)

Пример java
int[] arr = {7,2,5,3,9,1};
int k = 3;
Arrays.sort(arr);
int[] smallestK = Arrays.copyOfRange(arr, 0, k);
System.out.println(Arrays.toString(smallestK));
[1, 2, 3]

Для больших массивов предпочтительнее использовать selection algorithm (частичный алгоритм, O(n)) вместо полной сортировки O(n log n).

Сравнение производительности обычной и параллельной сортировок (псевдокод)

Пример java
// Для больших массивов стоит измерить:
long start = System.nanoTime();
Arrays.sort(bigArray);
long t1 = System.nanoTime() - start;
start = System.nanoTime();
Arrays.parallelSort(bigArrayCopy);
long t2 = System.nanoTime() - start;
System.out.println(t1 + " vs " + t2);
(Результаты зависят от размеров массива и числа ядер, пример: 120_000_000 vs 45_000_000)

Сортировка с пользовательским сравнивателем для сложных типов

Пример java
class Person { String name; int age; }
Person[] ppl = ...;
Arrays.sort(ppl, Comparator.comparingInt((Person p) -> p.age).thenComparing(p -> p.name));
(массив ppl отсортирован сначала по возрасту, затем по имени)

джава Arrays.sort function comments

En
Arrays.sort Сортирует массив