JavaRush /Java блог /Random UA /Колекції у Java | Java Collections

Колекції у Java | Java Collections

Стаття з групи Random UA
Вітання! За останні кілька занять ми сильно просунулися в освоєнні 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 , там є й інші методи.
Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ