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

undefined
19
Задача
Java Syntax Pro, 19 уровень, 6 лекция
Недоступна
Анализ потока чисел
Программа анализирует поток чисел. Логика программы следующая: 1. Метод hasNegativeEvenNumbers(Stream<Integer>) возвращает true, если во входящем потоке есть хотя бы одно отрицательное четное число и false, если таких чисел нет. Для поиска чисел в потоке используй метод anyMatch() объекта типа Strea
undefined
19
Задача
Java Syntax Pro, 19 уровень, 6 лекция
Недоступна
Просрочен ли товар?
В классе Solution метод hasExpiredProduct(Stream<Product>) возвращает true, если во входящем потоке товаров есть хотя бы один просроченный и возвращать false, если таких товаров нет. Чтобы это проверить, нужно у каждого товара в потоке сравнить поле expirationDate (годен до) типа LocalDate с текуще

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.


undefined
19
Задача
Java Syntax Pro, 19 уровень, 6 лекция
Недоступна
Как быть, если в списке есть элемент null
Задача метода printList(List<String>) — вывести в консоли все элементы списка, полученного как параметр, в том же порядке. Но есть один нюанс. В списке могут быть элементы, равные null. Твоя задача — вывести все элементы списка в консоли, а вместо null — фразу: Этот элемент равен null В методе pri

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(). Если программист знает, что реально через все фильтры пройдет 0 или 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();
undefined
19
Задача
Java Syntax Pro, 19 уровень, 6 лекция
Недоступна
Самый дорогой автомобиль
У автомобиля, представленного классом Car, есть две характеристики: название - поле name, цена - поле price. В классе Solution выполняются две операции поиска: - метод getMostExpensiveCar(Stream<Car>) ищет самый дорогой автомобиль в одном списке; - метод getMoreExpensiveCar(Stream<Car>, Car) в друго
undefined
19
Задача
Java Syntax Pro, 19 уровень, 6 лекция
Недоступна
Самый дешевый автомобиль
У автомобиля, представленного классом Car, есть две характеристики: название - поле name, цена - поле price. В классе Solution выполняются две операции поиска: - метод getCheapestCar(Stream<Car>) ищет самый дешевый автомобиль в одном списке; - метод getCheaperCar(Stream<Car>, Car) в другом списке ищ