Класс Collections в Java: методы и примеры - Вопросы
Всего: 7 вопросов
1. Что такое класс Collections в Java и какие методы в нём есть?
Что такое класс Collections в Java и какие методы в нём есть?
java.util.Collections — служебный (utility) класс Collection Framework, состоящий только из статических методов. Конструктор у него закрытый, объект создать нельзя, методы вызываются через имя класса: Collections.sort(list). Не путайте его с интерфейсом Collection.
Методы делятся на три группы:
- алгоритмы над списком:
sort(),binarySearch(),reverse(),shuffle(),swap(),fill(),copy(),rotate(); - вычисления над любой коллекцией:
max(),min(),frequency(),disjoint(); - фабрики списков и обёрток:
nCopies(),addAll(),emptyList(),singletonList(),unmodifiableList(),synchronizedList(),checkedList().
Методы, которые переставляют элементы, меняют список через set(), поэтому работают с ArrayList, LinkedList и Arrays.asList(). Списки из List.of(), nCopies() и unmodifiableList() на перестановку отвечают UnsupportedOperationException — сначала сделайте копию: new ArrayList<>(List.of(...)). Для массивов есть аналогичный класс Arrays.
2. Почему Collections.binarySearch() работает только с отсортированным списком и что он возвращает?
Почему Collections.binarySearch() работает только с отсортированным списком и что он возвращает?
Бинарный поиск на каждом шаге сравнивает ключ со средним элементом и отбрасывает половину списка — это корректно, только если список отсортирован. Метод возвращает индекс найденного элемента, а если элемента нет — -(точка вставки) - 1, где точка вставки — позиция, на которой элемент стоял бы в отсортированном списке. Обратно её получают так: -result - 1. Для ArrayList поиск занимает O(log n).
List<String> list = Arrays.asList("красный", "синий", "зеленый");
System.out.println(Collections.binarySearch(list, "зеленый")); // -1, хотя indexOf = 2
Collections.sort(list); // [зеленый, красный, синий]
System.out.println(Collections.binarySearch(list, "красный")); // 1
System.out.println(Collections.binarySearch(list, "черный")); // -4
Java не проверяет, отсортирован ли список, поэтому исключения не будет — только неверный результат. Если список отсортирован компаратором, например Collections.reverseOrder(), искать нужно с тем же компаратором: Collections.binarySearch(list, key, Collections.reverseOrder()).
3. Как перемешать, перевернуть список и поменять местами элементы методами shuffle(), reverse() и swap()?
Как перемешать, перевернуть список и поменять местами элементы методами shuffle(), reverse() и swap()?
Все три метода изменяют сам список и ничего не возвращают: Collections.reverse(list) переворачивает порядок элементов, Collections.swap(list, i, j) меняет местами элементы с индексами i и j, Collections.shuffle(list) переставляет элементы в случайном порядке.
List<String> list = Arrays.asList("красный", "синий", "зеленый", "черный");
Collections.reverse(list); // [черный, зеленый, синий, красный]
Collections.swap(list, 0, 3); // [красный, зеленый, синий, черный]
Collections.shuffle(list); // при каждом запуске свой порядок
Чтобы перемешивание повторялось от запуска к запуску (тесты, воспроизведение бага), передайте генератор с фиксированным начальным значением: Collections.shuffle(list, new Random(42)). Индекс вне [0, size()) в swap() даёт IndexOutOfBoundsException. Чтобы перевернуть список, не меняя исходный, сначала сделайте копию: new ArrayList<>(list).
4. Чем отличаются методы Collections.fill() и Collections.nCopies()?
Чем отличаются методы Collections.fill() и Collections.nCopies()?
Collections.fill(list, obj) заменяет каждый существующий элемент списка на obj и не меняет размер: пустой список после fill() останется пустым. Collections.nCopies(n, obj) создаёт новый неизменяемый список из n одинаковых элементов; чтобы его изменять, копируют в ArrayList:
List<String> filled = new ArrayList<>(Collections.nCopies(3, "черный"));
filled.add("белый"); // [черный, черный, черный, белый]
Без копии add() бросит UnsupportedOperationException, а nCopies(-1, "x") — IllegalArgumentException. Все позиции nCopies() ссылаются на один объект: после Collections.nCopies(3, new StringBuilder()) и get(0).append("x") список выводится как [x, x, x].
5. Как посчитать вхождения элемента и проверить, есть ли у коллекций общие элементы: frequency() и disjoint()?
Как посчитать вхождения элемента и проверить, есть ли у коллекций общие элементы: frequency() и disjoint()?
Collections.frequency(collection, obj) возвращает, сколько раз элемент встречается в коллекции, сравнивая через equals(); obj = null допустим. Collections.disjoint(c1, c2) возвращает true, если общих элементов нет (для двух пустых коллекций — тоже true). Оба метода принимают любую Collection.
List<String> colors = Arrays.asList("красный", "синий", "красный", null);
Collections.frequency(colors, "красный"); // 2
Collections.frequency(colors, "Красный"); // 0: equals() учитывает регистр
Collections.frequency(colors, null); // 1
Collections.disjoint(colors, List.of("красный", "оранжевый")); // false
Для собственных классов frequency() считает правильно, только если переопределён equals(). Самый частый элемент находят комбинацией: Collections.max(list, Comparator.comparingInt(x -> Collections.frequency(list, x))), но это O(n²) — для больших данных частоты считают за один проход в HashMap.
6. Для чего нужны методы Collections.addAll(), emptyList() и singletonList()?
Для чего нужны методы Collections.addAll(), emptyList() и singletonList()?
Collections.addAll(collection, e1, e2, ...) добавляет перечисленные элементы в существующую коллекцию и возвращает true, если она изменилась. Для Set, где все элементы уже были, вернётся false; для списка из Arrays.asList() — UnsupportedOperationException.
emptyList() и singletonList(obj) возвращают неизменяемые списки из нуля и одного элемента; add() на них бросает UnsupportedOperationException. Их возвращают из методов, чтобы не создавать лишний ArrayList: emptyList() каждый раз отдаёт один и тот же общий объект. Если вызывающий код должен наполнять результат, возвращайте new ArrayList<>().
С Java 9 вместо них часто пишут List.of() и List.of(obj). Разница: singletonList(null) допустим и даёт [null], а List.of(null) бросает NullPointerException.
7. Какие ошибки чаще всего допускают при работе с классом Collections?
Какие ошибки чаще всего допускают при работе с классом Collections?
binarySearch()на неотсортированном списке или с другим компаратором: исключения нет, результат просто неверный (например,-1для существующего элемента).sort(),shuffle(),reverse()на списке изList.of(),nCopies()илиunmodifiableList()—UnsupportedOperationException;addAll()наArrays.asList()— тоже.copy(dest, src)вnew ArrayList<>(10): важна не ёмкость, аsize(), равный 0, поэтомуIndexOutOfBoundsException: Source does not fit in dest. Независимую копию делают черезnew ArrayList<>(src).max()иmin()на пустой коллекции —NoSuchElementException; проверьтеisEmpty()или используйтеstream().max(cmp), который возвращаетOptional. Строки сравниваются по кодам символов, поэтомуCollections.max(Arrays.asList("кот", "собака", "ёж"))вернёт"ёж".fill()на пустом списке ничего не добавляет, аnCopies()с изменяемым объектом хранит одну и ту же ссылку во всех позициях.frequency()для класса без переопределённогоequals()сравнивает ссылки и не находит равные по содержимому объекты.
Сдвиг в rotate() ошибкой не бывает: отрицательный сдвигает влево, а значение больше размера берётся по модулю (rotate(list, 7) для пяти элементов — то же, что rotate(list, 2)).