Як вивчити Java Stream API [+5 Resources]

Потік у Java — це послідовність елементів, над якими можуть виконуватися послідовні або паралельні операції.

Може бути «n» кількість проміжних операцій і, нарешті, термінальна операція, після якої повертається результат.

Що таке потік?

Потоками можна керувати за допомогою Stream API, який був представлений у Java 8.

Уявіть Stream як виробничий конвеєр, у якому деякі товари потрібно виготовити, відсортувати, а потім упакувати для відправлення. У Java ці товари є об’єктами або колекціями об’єктів, операціями є виробництво, сортування та пакування, а конвеєр – це потік.

Компонентами потоку є:

  • Початковий вхід
  • Проміжні операції
  • Термінальна робота
  • Кінцевий результат

Давайте розглянемо деякі особливості потоку в Java:

  • Потік не є структурою даних у пам’яті; скоріше, це послідовність масивів, об’єктів або колекцій об’єктів, які обробляються певними методами.
  • Потоки мають декларативний характер, тобто ви вказуєте, що робити, але не вказуєте, як це робити.
  • Їх можна споживати лише один раз, оскільки вони ніде не зберігаються.
  • Потік не змінює вихідну структуру даних; він лише отримує від нього нову структуру.
  • Він повертає кінцевий результат, отриманий з методу final у конвеєрі.

Stream API проти обробки колекцій

Колекція — це структура даних у пам’яті, яка зберігає та обробляє дані. Колекції забезпечують такі структури даних, як Set, Map, List тощо, для зберігання даних. З іншого боку, потік — це спосіб ефективної передачі даних після їх обробки через конвеєр.

Ось приклад колекції ArrayList:-

import java.util.ArrayList;

public class Main {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(0, 3);
        System.out.println(list);
    }
}

Output: 
[3]

Як ви можете бачити в наведеному вище прикладі, ви можете створити колекцію ArrayList, зберігати в ній дані, а потім працювати з цими даними за допомогою різних методів.

Використовуючи потік, ви можете працювати з існуючою структурою даних і повертати нове змінене значення. Нижче наведено приклад створення колекції ArrayList і її фільтрації за допомогою потоку.

import java.util.ArrayList;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList();

        for (int i = 0; i < 20; i++) {
            list.add(i+1);
        }

        System.out.println(list);

        Stream<Integer> filtered = list.stream().filter(num -> num > 10);
        filtered.forEach(num -> System.out.println(num + " "));
    }
}

#Output

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 

У наведеному вище прикладі потік створюється за допомогою наявного списку, і список повторюється, щоб відфільтрувати значення, більші за 10. Зверніть увагу, що потік нічого не зберігає, список просто повторюється, а результат друкується. Якщо ви спробуєте надрукувати потік, ви отримаєте посилання на потік замість значень.

  Як дізнатися, хто приймає Google Pay

Робота над Java Stream API

Java Stream API приймає вихідну колекцію елементів або послідовність елементів, а потім виконує над ними операції для отримання кінцевого результату. Потік — це просто конвеєр, через який проходить послідовність елементів і якимось чином трансформується.

Потік можна створити з різних джерел, зокрема:

  • Колекція, наприклад список або набір.
  • Масив.
  • З файлів і шляхів до них за допомогою буфера.

Існує два типи операцій, які виконуються в потоці:

  • Проміжні операції
  • Термінальні операції

Проміжні та термінальні операції

Кожна проміжна операція повертає внутрішній новий потік, який перетворює вхідні дані за допомогою вказаного методу. Фактично нічого не пройдено; Замість цього він передається в наступний потік. Лише під час роботи терміналу потік проходить для отримання бажаного результату.

Наприклад, у вас є список із 10 чисел, які ви хочете відфільтрувати, а потім зіставити з чимось. Не кожен елемент списку буде проходити відразу, щоб отримати відфільтрований результат і відобразити його на щось інше. Замість цього окремі елементи будуть перевірені, і якщо вони відповідають умові, вони будуть зіставлені. Нові потоки для кожного елемента.

Операцію з картою буде виконано для окремих елементів, які задовольняють фільтр, а не для всього списку. А під час роботи терміналу вони проходять і об’єднуються в єдиний результат.

Після виконання термінальної операції потік витрачається і більше не може бути використаний далі. Ви повинні створити новий потік, щоб знову виконати ті самі операції.

Джерело: The Bored Dev

З поверхневим розумінням того, як працюють потоки, давайте перейдемо до деталей реалізації потоків у Java.

  Як розмити фон на Zoom?

#1. Порожній потік

Створіть порожній потік за допомогою пустого методу Stream API.

import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        Stream emptyStream = Stream.empty();
        System.out.println(emptyStream.count());
    }
}

Output:
0

Тут, якщо ви надрукуєте кількість елементів у цьому потоці, ви отримаєте 0 як результат, оскільки це порожній потік без елементів. Порожні потоки дуже корисні для уникнення винятків нульового покажчика.

#2. Потік із колекцій

Такі колекції, як Lists і Set, надають метод stream(), який дозволяє створювати потік із колекції. Потім створений потік можна пройти, щоб отримати кінцевий результат.

ArrayList<Integer> list = new ArrayList();

for (int i = 0; i < 20; i++) {
    list.add(i+1);
}

System.out.println(list);

Stream<Integer> filtered = list.stream().filter(num -> num > 10);
filtered.forEach(num -> System.out.println(num + " "));

#Output

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 

#3. Потік із масивів

Метод Arrays.stream() використовується для створення потоку з масиву.

import java.util.Arrays;

public class Main {
    public static void main(String[] args) {
        String[] stringArray = new String[]{"this", "is", "techukraine.net"};
        Arrays.stream(stringArray).forEach(item -> System.out.print(item + " "));
    }
}

#Output

this is techukraine.net 

Ви також можете вказати початковий і кінцевий індекси елементів для створення потоку. Початковий індекс є включним, тоді як кінцевий індекс є виключним.

String[] stringArray = new String[]{"this", "is", "techukraine.net"};
Arrays.stream(stringArray, 1, 3).forEach(item -> System.out.print(item + " "));

Output:
is techukraine.net

#4. Пошук мінімальних і максимальних чисел за допомогою потоків

Доступ до максимальної та мінімальної кількості колекції чи масиву можна отримати за допомогою компараторів у Java. Методи min() і max() приймають компаратор і повертають необов’язковий об’єкт.

Додатковий об’єкт – це об’єкт-контейнер, який може містити або не містити ненульове значення. Якщо він містить ненульове значення, виклик методу get() для нього поверне значення.

import java.util.Arrays;
import java.util.Optional;

public class MinMax {
    public static void main(String[] args) {
        Integer[] numbers = new Integer[]{21, 82, 41, 9, 62, 3, 11};

        Optional<Integer> maxValue = Arrays.stream(numbers).max(Integer::compare);
        System.out.println(maxValue.get());

        Optional<Integer> minValue = Arrays.stream(numbers).min(Integer::compare);
        System.out.println(minValue.get());
    }
}

#Output
82
3

Навчальні ресурси

Тепер, коли ви маєте базове уявлення про потоки в Java, ось 5 ресурсів, які допоможуть вам добре ознайомитися з Java 8:

#1. Java 8 в дії

Ця книга є посібником, який демонструє нові функції Java 8, включаючи потоки, лямбда-вирази та програмування у функціональному стилі. Тести та запитання для перевірки знань також є частиною книги, яка допоможе вам відновити вивчене.

  Як виправити збій програм на iPhone або iPad

Ви можете отримати цю книгу в м’якій обкладинці, а також у форматі аудіокниги на Amazon.

#2. Java 8 Lambda: функціональне програмування для мас

Ця книга спеціально розроблена, щоб навчити основних розробників Java SE, як додавання лямбда-виразів впливає на мову Java. Він містить зрозумілі пояснення, вправи з кодом і приклади, які допоможуть вам освоїти лямбда-вирази Java 8.

Він доступний у форматі м’якої палітурки та у виданні Kindle на Amazon.

#3. Java SE 8 для справді нетерплячих

Якщо ви досвідчений розробник Java SE, ця книга проведе вас через удосконалення Java SE 8, потоковий API, додавання лямбда-виразів, покращення паралельного програмування в Java та деякі функції Java 7, які більшість людей не знають. не знаю про.

Він доступний лише у м’якій обкладинці на Amazon.

#4. Вивчіть функціональне програмування на Java з лямбда-виразами та потоками

Цей курс від Udemy вивчає основи функціонального програмування в Java 8 і 9. Лямбда-вирази, посилання на методи, потоки та функціональні інтерфейси – це концепції, на яких зосереджено цей курс.

Він також містить купу Java-головоломок і вправ, пов’язаних із функціональним програмуванням.

#5. Бібліотека класів Java

Бібліотека класів Java є частиною основної спеціалізації Java, яку пропонує Coursera. Він навчить вас, як писати безпечний код за допомогою Java Generics, зрозуміти бібліотеку класів, що складається з понад 4000 класів, як працювати з файлами та обробки помилок під час виконання. Проте є деякі передумови для проходження цього курсу:

  • Введення в Java
  • Вступ до об’єктно-орієнтованого програмування на Java
  • Об’єктно-орієнтовані ієрархії в Java

Заключні слова

Java Stream API і введення функцій Lambda в Java 8 спростили й покращили багато речей у Java, наприклад паралельну ітерацію, функціональні інтерфейси, менше коду тощо.

Однак потоки мають деякі обмеження; їх найбільшим обмеженням є те, що їх можна споживати лише один раз. Якщо ви є розробником Java, згадані вище ресурси можуть допомогти вам зрозуміти ці теми більш детально, тому обов’язково ознайомтеся з ними.

Ви також можете дізнатися про обробку винятків у Java.