Вітання! За останні кілька занять ми сильно просунулися в освоєнні ArrayList. Однак, протягом цього часу ми робабо лише найпростіші операції: видалення, вставку, виведення в консоль. Звичайно, на цьому перелік завдань, з якими стикаються розробники при використанні ArrayList , не вичерпується. Пам'ятаєш лекцію про масиви та клас Arrays ? Він був розроблений творцями Java спеціально для того, щоб вирішувати типові завдання, з якими програмісти стикаються під час роботи з масивами. А що з ArrayList? Напевно, є якийсь список типових завдань і для нього. Чи були всі вони реалізовані в якомусь окремому класі, чи нам доведеться щоразу писати потрібну поведінку вручну? Зрозуміло, писати все самим не потрібно. Найбільш поширені операції, які здійснюються при використанні колекцій Java, вже були реалізовані в спеціальному статичному класі Collections.
Колекції у 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 , там є й інші методи.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ