1. Перевірка

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

Клас Stream має три стандартних методи, які не конструюють потоки, а перевіряють, які дані містяться в цих потоках. Це методи anyMatch(), allMatch() і noneMatch().

Метод boolean anyMatch(правило)

Цей метод перевіряє, чи є в потоці щонайменше один елемент, який відповідає правилу, переданому в метод. Якщо такий елемент є, метод повертає true, інакше — false.

Приклади

Код Примітка
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.anyMatch(x -> x > 0);

true
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.anyMatch(x -> x > 0);

true
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).anyMatch(x -> x > 0);

false

В останньому прикладі ми спочатку відфільтровуємо (пропускаємо крізь фільтр) усі елементи, менші за нуль, а потім уже серед них виконуємо перевірку, чи є принаймні один елемент, більший за нуль. Ясна річ, таких елементів там уже немає.

Метод boolean allMatch(правило)

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

Код Примітка
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.allMatch(x -> x > 0);
true
(усі елементи більші за нуль)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.allMatch(x -> x > 0);
false
(є елементи, менші або рівні нулю)
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).allMatch(x -> x < 0);
true
(відфільтрували елементи, менші за нуль)

В останньому прикладі ми спочатку пропускаємо крізь фільтр тільки елементи, менші за нуль, а потім уже серед них виконуємо перевірку, чи всі вони менші за нуль. Перевірка проходить успішно.

Метод boolean noneMatch(правило)

Метод noneMatch() перевіряє, чи в потоці немає жодного елемента, що відповідає переданому правилу. Метод, протилежний за змістом до методу anyMatch().

Код Примітка
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);
boolean result = stream.noneMatch(x -> x > 0);

false
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.noneMatch(x -> x > 0);

false
Stream<Integer> stream = Stream.of(1, -2, 3, -4, 5);
boolean result = stream.filter(x -> x < 0).noneMatch(x -> x > 0);

true

4
Задача
Java Core,  6 рівень5 лекція
Недоступна
join: у потрібний час у потрібному місці
join: у потрібний час у потрібному місці
18
Задача
Java Core,  6 рівень5 лекція
Недоступна
Horse Racing
Horse Racing

2. Службові класи: клас Optional

Іноді програмістам дуже незручно працювати з посиланнями на null. Приміром, ви порівнюєте два рядки. Якщо обидві змінні не null, тоді можна просто викликати s1.equals(s2), і все працюватиме. А от якщо s1 може бути null, доведеться писати код, який враховує цю ситуацію, щоб не виник NullPointerException.

Тому програмісти придумали службовий клас Optional<T>. Його код має приблизно такий вигляд:

Код Примітка
class Optional<Tип>
{
   private final Tип value;
   private Optional() { this.value = null;}
   private Optional(value) { this.value = value;}
   public static <Tип> Optional<Tип> of(Tип value)
   {
      return new Optional<Tип>(value);
   }

   public boolean isPresent()
   {
      return value != null;
   }

   public boolean isEmpty()
   {
      return value == null;
   }

   public Tип get()
   {
      if (value == null)
      {
         throw new NoSuchElementException();
      }
      return value;
   }

   public Tип orElse(Tип other)
   {
      return value != null ? value : other;
   }

   public Tип orElseThrow()
   {
      if (value == null)
      {
         throw new NoSuchElementException();
      }
      return value;
   }
}










Перевіряє, чи всередині є значення (посилання не є null)



Перевіряє, чи зберігає об'єкт посилання на null




Повертає значення, яке зберігає. Кидає виняток, якщо значення немає.







Повертає значення або, якщо всередині зберігається null, то передане в метод друге значення



Повертає значення або кидає виняток, якщо значення немає.

Призначення цього класу — просто зберігати в собі об'єкт T (посилання на об'єкт типу T). Посилання на об'єкт всередині класу Optional<T> може бути null.

Цей клас дає програмістам змогу писати красивіший код. Порівняйте:

З використанням Optional Без використання Optional
public void printString(String s)
{
   Optional<String> str = Optional.ofNullable(s);
   System.out.println(str.orElse(""));
}
public void printString(String s)
{
   String str = s != null ? s : "";
   System.out.println(str)
}

Один об'єкт Optional завжди можна порівняти з іншим об'єктом Optional за допомогою методу equals, навіть якщо вони зберігають у собі посилання на null.

У загальних рисах клас Optional уможливлює «красивіший» запис перевірки на null і дій у разі, якщо всередині об'єкта Optional зберігається null.


9
Задача
Java Core,  6 рівень5 лекція
Недоступна
Просування на політичних дебатах
Просування на політичних дебатах

3. Пошук елементів

Повернімося до класу Stream. Клас Stream має ще 4 методи, що дають змогу шукати елементи в потоці. Це методи findFirst(), findAny(), min() і max().

Метод Optional<T> findFirst()

Метод findFirst() просто повертає перший елемент із потоку, і все — на цьому його робота завершується.

Цікаво, що метод повертає не об'єкт типу T, а обгортку над ним — об'єкт типу Optional<T>. Це зроблено для того, щоб ніколи не стикатися із ситуацією, коли метод не знаходить об'єкт і повертає null.

Приклад:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Привіт", "як", "справи?");
String str = list.stream().findFirst().get(); // Привіт

Для кращого розуміння запишімо останній рядок у кілька рядків:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Привіт", "як", "справи?");

Stream<String> stream = list.stream();
Optional<String> result = stream.findFirst();
String str = result.get(); // Привіт

Останній метод get() — це просто витягання значення, що зберігається всередині об'єкта Optional.

Метод Optional<T> findAny()

Метод findAny() повертає будь-який елемент з потоку й на цьому завершується. Цей метод — аналог методу findFirst(), тільки для потоків, які обробляються паралельно.

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

Якщо елементів, які пройшли всі фільтри, багато, а програмісту важливо отримати саме найперший із них, слід викликати метод findFirst(). Якщо програміст знає, що реально крізь усі фільтри пройде щонайбільше 1 елемент, тоді досить просто викликати findAny() — так буде швидше.

Метод Optional<T> min(Comparator<T>)

Метод min() порівнює всі елементи потоку за допомогою об'єкта comparator і повертає мінімальний елемент. Найзручніше задати об'єкт-компаратор за допомогою лямбда-функції.

Приклад — пошук рядка мінімальної довжини:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Привіт", "як", "справи?");
String min = list.stream().min( (s1, s2)-> s1.length()-s2.length() ).get();

Метод Optional<T> max(Comparator<T>)

Метод max() порівнює всі елементи потоку за допомогою об'єкта comparator і повертає максимальний елемент. Найзручніше задати об'єкт-компаратор за допомогою лямбда-функції.

Приклад — пошук рядка максимальної довжини:

ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Привіт", "як", "справи?");
String max = list.stream().max( (s1, s2)-> s1.length()-s2.length() ).get();
4
Задача
Java Core,  6 рівень5 лекція
Недоступна
Справедливість
Справедливість
9
Задача
Java Core,  6 рівень5 лекція
Недоступна
Розташуй виклики методів join()
Розташуй виклики методів join()