Привет! За последние несколько занятий мы сильно продвинулись в освоении ArrayList.
Однако, в течение этого времени мы совершали только простейшие операции: удаление, вставку, вывод в консоль. Конечно, на этом список задач, с которыми сталкиваются разработчики при использовании ArrayList, не исчерпывается.
Помнишь лекцию о массивах и классе Arrays? Он был разработан создателями Java специально для того, чтобы решать типовые задачи, с которыми программисты сталкиваются при работе с массивами.
А что с ArrayList? Наверняка есть какой-то список типовых задач и для него. Были ли они все реализованы в каком-то отдельном классе, или нам придется каждый раз писать нужное поведение вручную?
Разумеется, писать все самим не потребуется.
Наиболее распространенные операции, которые совершаются при использовании коллекций в Java, уже были реализованы в специальном статическом классе Collections.
![Класс Collections - 1]()

Коллекции в Java
“Коллекции” — общее название для нескольких структур данных в Java. Данные можно хранить многими разными способами. Мы пока изучили только класс ArrayList, где данные хранятся в массиве. С остальными коллекциями мы познакомимся позднее. Сейчас достаточно понимать что класс Collections рассчитан на работу не только с ArrayList, но и с другими видами коллекций в Java (отсюда, собственно, и его название). Итак, какие же задачи при работе с ArrayList позволяет решить класс Collections? Первое и самое очевидное — сортировка. В лекции о массивах мы рассматривали пример с числами, а теперь рассмотрим пример со строками. Для сортировки содержимого коллекций в классе Collections реализован методsort()
:
public class Main {
public static void main(java.lang.String[] args) {
String mercury = new String("Меркурий");
String venus = new String("Венера");
String earth = new String("Земля");
String mars = new String("Марс");
String jupiter = new String("Юпитер");
String saturn = new String("Сатурн");
String uranus = new String("Уран");
String neptune = new String("Нептун");
ArrayList<String> solarSystem = new ArrayList<>(Arrays.asList(mercury, venus, earth, mars,
jupiter, saturn, uranus, neptune));
Collections.sort(solarSystem);
System.out.println(solarSystem);
}
}
Вывод:
[Венера, Земля, Марс, Меркурий, Нептун, Сатурн, Уран, Юпитер]
Строки были отсортированы в алфавитном порядке!
Почему именно в алфавитном? В классе String
запрограммировано, как именно строки сравниваются между собой (как раз — по алфавиту). Для классов, которые ты будешь создавать сам, можешь реализовать свой механизм сравнения, но об этом мы поговорим в других лекциях.
Кроме того, класс Collections позволяет найти минимальный и максимальный элемент в ArrayList
. Это делается с помощью методов min()
и max()
:
public static void main(java.lang.String[] args) {
ArrayList<Integer> numbers = new ArrayList<>(Arrays.asList(1,2,3,4,5,6,7));
System.out.println(Collections.max(numbers));
System.out.println(Collections.min(numbers));
}
Вывод:
7
1
Это, конечно, гораздо удобнее, чем вручную писать код для прохождения по всем элементам и поискам наибольшего/наименьшего элемента :)
Еще один крайне полезный метод — reverse()
. Если бы нам нужно было “перевернуть” список, чтобы элементы шли в обратном порядке — как бы мы это делали? Вероятно, написать такой алгоритм самому было бы не так просто :)
К счастью, метод reverse()
уже это умеет. Например, нам не нравится как метод sort()
отсортировал наши планеты в алфавитном порядке, и мы хотим изменить порядок на обратный — от Я до А:
public class Main {
public static void main(java.lang.String[] args) {
String mercury = new String("Меркурий");
String venus = new String("Венера");
String earth = new String("Земля");
String mars = new String("Марс");
String jupiter = new String("Юпитер");
String saturn = new String("Сатурн");
String uranus = new String("Уран");
String neptune = new String("Нептун");
ArrayList<String> solarSystem = new ArrayList<>(Arrays.asList(mercury, venus, earth, mars,
jupiter, saturn, uranus, neptune));
Collections.sort(solarSystem);
Collections.reverse(solarSystem);
System.out.println(solarSystem);
}
}
Вывод:
[Юпитер, Уран, Сатурн, Нептун, Меркурий, Марс, Земля, Венера]
Кстати, мы тут часто говорим о сортировке, порядке элементов и т.д.
А что, если задача у нас будет прямо противоположная?
Например, мы пытаемся реализовать механизм работы лотереи. Мы добавили в барабан 100 чисел, которые по одному должны появляться на экране. Кто из участников первым зачеркнет все числа на своем билете — побеждает.
Реализовать такой механизм очень легко с помощью метода shuffle()
:
public class Main {
public static void main(java.lang.String[] args) {
ArrayList<Integer> lottery = new ArrayList<>(100);
for (int i = 1; i <= 100; i++) {
lottery.add(i);//добавляем в барабан числа от 1 до 100
}
Collections.shuffle(lottery);//перемешиваем
System.out.println("Внимание! Из барабана появляются первые 10 чисел!");
for (int i = 0; i < 10; i++) {
System.out.println(lottery.get(i));
}
}
}
Вывод:
Внимание! Из барабана появляются первые 10 чисел!
32
61
4
81
25
8
66
35
42
71
Вот так просто! Задача решена, а наш кусочек игры написан :)
Теперь представим другую ситуацию. Ранее мы создали список solarSystem
с перечисленными в нем планетами.
И он нас, вроде как, всем устраивает, если бы не одно но: из него можно удалять элементы и добавлять новые! Это явно не то поведение, которое мы ждем: Солнечная система в нашей программе должна быть в неизменном состоянии.
В классе Collections есть очень интересный метод — unmodifiableList()
. Он создает из переданного списка его неизменяемый вариант. В него нельзя будет ни добавить, ни удалить элемент.
В случае со списком планет Солнечной системы это именно то, что нам нужно!
public class Main {
public static void main(java.lang.String[] args) {
String mercury = new String("Меркурий");
String venus = new String("Венера");
String earth = new String("Земля");
String mars = new String("Марс");
String jupiter = new String("Юпитер");
String saturn = new String("Сатурн");
String uranus = new String("Уран");
String neptune = new String("Нептун");
List<String> solarSystem = Collections.unmodifiableList(new ArrayList<>(Arrays.asList(mercury, venus, earth, mars,
jupiter, saturn, uranus, neptune)));
solarSystem.add("Плутон");//попробуем добавить новый элемент
}
}
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Collections.java:1075)
at Main.main(Main.java:21)
Ошибка в solarSystem
теперь нельзя ничего добавлять!
Единственное, на что в данном случае нужно обратить внимание — тип переменной должен быть List<>
, а не ArrayList<>
(данный метод возвращает объект именно такого типа, общего для всех видов списков).
Еще одна рядовая ситуация, которая может произойти во время работы — программист добавил элементы в неправильном порядке.
Если такое произошло, и Меркурий и Нептун неожиданно поменялись местами — исправить эту оплошность нам поможет метод swap()
:
public class Main {
public static void main(java.lang.String[] args) {
String mercury = new String("Меркурий");
String venus = new String("Венера");
String earth = new String("Земля");
String mars = new String("Марс");
String jupiter = new String("Юпитер");
String saturn = new String("Сатурн");
String uranus = new String("Уран");
String neptune = new String("Нептун");
ArrayList<String> solarSystem = new ArrayList<>(Arrays.asList(neptune, venus, earth, mars
, jupiter, saturn, uranus, mercury));// неправильный порядок планет
System.out.println(solarSystem);
Collections.swap(solarSystem, solarSystem.indexOf(mercury), solarSystem.indexOf(neptune));
System.out.println(solarSystem);
}
}
В метод swap()
мы передали наш список, а также индексы двух элементов, которые нужно поменять местами. Обрати внимание: метод работает именно с индексами, а не со ссылками. Поэтому здесь нам понадобился метод ArrayList.indexOf()
.
Вывод:
[Нептун, Венера, Земля, Марс, Юпитер, Сатурн, Уран, Меркурий]
[Меркурий, Венера, Земля, Марс, Юпитер, Сатурн, Уран, Нептун]
Напоследок познакомимся с очень интересным методом — disjoint()
.
Он проверяет, есть ли у двух коллекций пересечения, то есть хоть один одинаковый элемент. Если нет — возвращает true
, если есть — false
.
public class Main {
public static void main(java.lang.String[] args) {
String mercury = new String("Меркурий");
String venus = new String("Венера");
String earth = new String("Земля");
String mars = new String("Марс");
String jupiter = new String("Юпитер");
String saturn = new String("Сатурн");
String uranus = new String("Уран");
String neptune = new String("Нептун");
ArrayList<String> solarSystemPart1 = new ArrayList<>(Arrays.asList(mercury, venus, earth, mars));
ArrayList<String> solarSystemPart2 = new ArrayList<>(Arrays.asList(jupiter, saturn, uranus, neptune));
System.out.println(Collections.disjoint(solarSystemPart1, solarSystemPart2));
}
}
Как видишь, в наших двух списках элементы полностью разные, поэтому программа выводит true
.
Вот такой интересный и очень полезный класс. Как и Arrays
, он выполняет вместо нас много рутинной, черновой работы, позволяя сосредоточиться на других вещах.
Почитай о нем в документации Oracle, там есть и другие методы.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Arrays.asList
: Если обратиться к документации поArrays.asList
, то можно прочесть следующее: . То бишь мы получаемList
с фиксированным размером, а, значит, добавить в него новый элемент не получится и так, безCollections.unmodifiableList
.int
можем присвоитьbyte
. Почти, потому что для примитивных переменных происходит преобразование типов. Отличие в том, что при преобразовании типов меняется сама ячейка памяти с данными (был 1 байт, стало 4), а с приведением - нет (то есть сам объект не изменяется, меняется тип ссылки).