1. Проверка
Думаю, вам уже скучно изучать, как конструировать цепочки потоков данных. Хочется наконец-то с этими данными что-то делать.
У класса Stream
есть три стандартных метода, которые не конструируют потоки, а проверяют, что за данные находятся в этих потоках. Это методы: anyMatch()
, allMatch()
и noneMatch()
.
Метод boolean anyMatch(правило)
Этот метод проверяет, что в потоке есть хотя бы один элемент, который удовлетворяет правилу, которое передается в метод. Если такой элемент есть, метод возвращает true
, иначе — false
.
Примеры
Код | Примечание |
---|---|
|
|
|
|
|
|
В последнем примере мы сначала отфильтровываем (пропускаем через фильтр) все элементы меньше нуля, а затем уже среди них проводим проверку, есть ли хотя бы один элемент больше нуля. Ясное дело, таких элементов там уже нет.
Метод boolean allMatch(правило)
Этот метод проверяет, что все элементы в потоке соответствуют правилу. Правило передается в метод в качестве параметра:
Код | Примечание |
---|---|
|
(все элементы больше нуля)
|
|
(есть элементы меньше или равны нулю)
|
|
(отфильтровали элементы меньше нуля)
|
В последнем примере мы сначала пропускаем через фильтр только элементы меньше нуля, а потом уже среди них выполняем проверку, что все элементы меньше нуля. Проверка проходит успешно.
Метод boolean noneMatch(правило)
Метод noneMatch()
проверяет, что в потоке нет ни одного элемента, который соответствует переданному правилу. Противоположный по смыслу метод к методу anyMatch()
.
Код | Примечание |
---|---|
|
|
|
|
|
|
2. Служебные классы: класс Optional
Иногда программистам очень неудобно работать с ссылками на null
. Например, вы сравниваете две строки. Если обе переменные не null
, тогда можно просто вызвать s1.equals(s2)
, и все будет работать. А вот если s1
может быть null
, придется писать код, который учитывает эту ситуацию, чтобы не возникло NullPointerException
.
Поэтому программисты придумали служебный класс Optional<T>
. Выглядит его код примерно так:
Код | Примечание |
---|---|
|
Проверяет, что внутри находится значение (ссылка не null )
Проверяет, что объект хранит ссылку на null
Возвращает значение, которое хранит. Кидает исключение, если значения нет. Возвращает значение, или если внутри хранится null , то переданное в метод второе значение
Возвращает значение или кидает исключение, если значения нет. |
Цель этого класса – просто хранить в себе объект T (ссылку на объект типа T). Ссылка на объект внутри класса Optional<T>
может быть null
.
Этот класс позволяет писать программистам код немного красивее. Сравните:
С использованием Optional | Без использования Optional |
---|---|
|
|
Один объект Optional
всегда можно сравнить с другим объектом Optional
через метод equals
, даже если они хранят в себе ссылки на null
.
Грубо говоря, класс Optional позволяет «более красиво» записывать проверки на null
и действия в случае, если внутри объект Optional
хранится null
.
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();
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ