JavaRush/Java блог/Java Developer/Коллекции в Java | Java Collections
Автор
Jesse Haniel
Главный архитектор программного обеспечения в Tribunal de Justiça da Paraíba

Коллекции в Java | Java Collections

Статья из группы Java Developer
участников
Привет! За последние несколько занятий мы сильно продвинулись в освоении 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, там есть и другие методы.
Комментарии (183)
  • популярные
  • новые
  • старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
{Java_Shark}
Уровень 19
21 марта, 04:53
Хорошая лекция, автору++
Kaz
Уровень 17
19 февраля, 16:06
мне нра лекции этого парня..
Максим Li Java Developer
1 декабря 2023, 05:35
Узнал новые методы, и это хорошо!
Andrey T.
Уровень 28
3 октября 2023, 12:24
норм
Denis Gritsay
Уровень 37
27 сентября 2023, 21:17
👍
Alexander Rozenberg
Уровень 32
18 июля 2023, 13:42
fine
Anonymous #2574540
Уровень 20
23 июня 2023, 13:51
Спасибо, были методы о которых не знал
No Name
Уровень 32
11 июня 2023, 02:09
+ статья в копилку
Ислам
Уровень 33
31 мая 2023, 12:28
Nice
dude.from.odessa
Уровень 32
16 апреля 2023, 23:54
Метод Collections.unmodifiableList() возвращает неизменяемую оболочку (wrapper) над исходным списком. Это означает, что любые изменения, попытки добавления, удаления или изменения элементов списка, будут вызывать UnsupportedOperationException. Однако, если изменения происходят в исходном списке, эти изменения будут отражены в неизменяемом списке, поскольку он просто обертывает исходный список. Пример :
List<String> originalList = new ArrayList<>();
originalList.add("one");
originalList.add("two");

List<String> unmodifiableList = Collections.unmodifiableList(originalList);

System.out.println(unmodifiableList); // [one, two]

originalList.add("three");

System.out.println(unmodifiableList); // [one, two, three]
ElenaN
Уровень 37
17 октября 2023, 13:25
Я тоже поэкспериментировала с этим методом и была удивлена результату, считаю, что такие моменты надо в лекции прояснять... Спасибо за уточнение!