З кожною новою версією Java стає все багатшим і багатшим. Хоча найчастіше основа багатств закладено у ранніх версіях, але мова продовжував удосконалюватися як і методології, і у реалізації. Колекції Java не є винятком. Основний каркас колекцій з'явився у версії J2SE 1.2 і продовжував розвиватися, зазнаючи змін, які більше радували, ніж засмучували. З виходом JDK 5 колекції стали зручнішими, швидше, а працювати з ними стало легше. Це призвело до того, що програмісти почали інтенсивніше їх експлуатувати. Виробабося деякі патерни по роботі з ними, які без жодного сумніву ефективні. Але з появою JDK 8 колекції знову стали кращими, а краще вони стали завдяки потокам. Очевидно, завдяки тому, що колекцію можна подати у вигляді потоків, змінюватиметься і методика роботи з ними. Тому я хочу показати, як звичні та зрозумілі рішення з колекціями стають ще простішими.
- Приклад 1. Простіше не буває
- Приклад 2. Знайдемо парні значення у списку та виведемо їх у консоль
- Приклад 3. Порахуємо скільки слів у списку має довжину 5 символів
- Приклад 4. Вивести унікальні слова
- Приклад 5. Довгі слова
- Приклад 6. Слова з цифрами
- Приклад 7. Виділяємо числа
Приклад 1. Простіше не буває
Звичайно почнемо з найпростішого, пробіжимося всіма елементами колекції і виведемо всі елементи.// создадим и заполним список
List<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 5, 6, 11, 3, 15, 7, 8);
// а теперь
// быстрый for по всем елементам, только для коллекций
for (Integer i:list){
System.out.println(i);
}
//но мы уже живем в JDK 8
//а значит нужно так
list.stream().forEach(System.out::println);
Як ви помітабо, є новий синтаксис, який, на мій погляд, новачка Java, набагато простіше. Отже, що видно у новому синтаксисі:
берем_список(list).превращаем_в_поток(stream).перебираем_все_элементы(forEach)(тут_интуитивно_понятно)
System.out::println
— посилання на статичний метод, який виводить рядок на консоль Замість посилання на статичний метод можна використовувати трохи інший, поки що менш зрозумілий запис:
list.stream().forEach(i -> System.out.println(i));
у цьому записі використовується лямбда-вираз. І так, щоб навчитися працювати з потоками, потрібно буде вивчити лямбда-вирази – вони чудові. Далі я не показуватиму як працювати з колекціями використовуючи тільки потоки, розраховуючи на те, що з традиційними способами ви познайомабося в ході курсу.
Приклад 2. Знайдемо парні значення у списку та виведемо їх у консоль
list.stream().filter(i -> i%2==0).forEach(System.out::println);
Все завдання вирішено в один рядок. Сподіваюся вам подобається працювати в один рядок. За допомогою методу filter
ми профільтрували потік і те, що залишилося, вивели на консоль. Фільтр дуже потужна штука, яка здатна допомогти у найнесподіваніших випадках. Давайте подивімося і змінимо умови завдання. Наприклад, нам потрібно порахувати скільки парних чисел у списку:
long count = list.stream().filter(i -> i%2==0).count();
І знову в один рядок. Якось здається, все просто. У фільтрі ми використовували лямбда-вираз, тим самим помістивши в новий потік лише парні числа, а потім до нового потоку застосували count
, який і вважав, скільки елементів у новому потоці.
Приклад 3. Порахуємо скільки слів у списку має довжину 5 символів
Пограли з цілими числами, тепер пограємося зі словами.List<String> list = new ArrayList<>();
Collections.addAll(list, "разые", "слова", "интересные", "і", "ні", "дуже");
System.out.println(list.stream().filter(w -> w.length() == 5).count());
Ми знову скористалися фільтром. У фільтрі за допомогою лямбда-вираження вивели новий потік, а далі зрозумілий count
порахував, скільки в новому потоці елементів.
Приклад 4. Вивести унікальні слова
Знайоме завдання, коли ми прочитали в колекцію з файлу багато різних слів, а тепер нам потрібні унікальні.List<String> list = new ArrayList<>();
Collections.addAll(list, "Вася", "Таня", "Оля", "Вася", "Оля", "Сергей");
list.stream().distinct().forEach(System.out::println);
Основна дія була зроблена над потоком за допомогою distinct
. Далі я пропоную подивитись деякі наші завдання з курсу за допомогою потоків
Приклад 5. Довгі слова
На 9-му рівні Java Core, в 11 лекції є цікаве завдання, в ній потрібно записати через кому в Файл2 слова, довжина яких строго більше 6. Який би город не городабо, я пропоную такий хід рішення:-
З файлу джерела читаємо усі слова до списку.
-
Потім виконуємо наступний рядок
Optional<String> rezult = list.stream() .filter(w->w.length()>6) .reduce((w1,w2)->w1+", "+w2);
-
result.get()
записуємо у файл.
Приклад 6. Слова з цифрами
Записати через пробіл у файл2 всі слова, які містять цифри, наприклад, а1 або abc3d. Це теж умова з нашого задачника, як ви здогадалися, рішення просте.Optional<String> rezult = list.stream()
.filter(w->w.matches(".*?\\d+.*?"))
.reduce((w1,w2)->w1+" "+w2);
Профільтрували потік за допомогою регулярного виразу, а потім reduce та лямбда-вираз. Як багато спільного із попереднім завданням.
Приклад 7. Виділяємо числа
Все завдання звучить так:- Рахувати з консолі 2 імені файлу.
- Вивести у другий файл усі числа, які є у першому файлі.
- Числа виводити через пропуск.
- Закрити потоки.
Optional<String> rezult = list.stream().filter(w->w.matches("\\d+"))
.reduce((w1,w2)->w1+" "+w2);
System.out.println(rezult.get());
За допомогою потоків завдання вирішується дуже простим способом. Але, диво, порівняйте це рішення з двома попередніми самостійно. Завершуючи статтю, я хочу Вам зізнатися: хлопці, я шахраював, коли підбирав приклади. Справа в тому, що я вибрав найпростіші приклади, щоб показати Вам на знайомих завданнях незнайому тему. Звичайно, потоки використовуються як для простих, так і для складніших завдань. Але як підкреслив у своїй книзі Хорстман «Потоки даних діють за принципом «що, а не як робити», а отже багато, раніше складних завдань, можуть стати більш простими. Не знаю як Вам, але мені потоки сподобалися, сподіваюся, я не відбив у Вас бажання їх повчити. І ще дещо поясню:
- Я не ставив собі за мету навчити читача використовувати потоки в колекціях, не настільки я досвідчений наставник. Я хотів показати, що потоки це просто і дуже цікаво! Взагалі, це необхідність.
- Чим більше я розумію потоки, тим більше бачу завдань, де вони вирішують усі проблеми із задачника курсу, а отже, потоки придумали недаремно.
- З потоками не тільки просто працювати, але вони ще мають важливу перевагу - при роботі з великими масивами даних потоки частіше продуктивніші.
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ