1. Stream
Stream — это объект для универсальной работы с данными. Мы указываем, какие операции хотим провести, при этом не заботясь о деталях реализации. Например, взять элементы из списка сотрудников, выбрать тех, кто младше 40 лет, отсортировать по фамилии и поместить в новый список. Или чуть сложнее, прочитать все json-файлы, находящиеся в папке books, десериализировать в список объектов книг, обработать элементы всех этих списков, а затем сгруппировать книги по автору.
Данные могут быть получены из источников, коими являются коллекции или методы, поставляющие данные. Например, список файлов, массив строк, метод range() для числовых промежутков и т.д. То есть, стрим использует существующие коллекции для получения новых элементов, это ни в коем случае не новая структура данных.
К данным затем применяются операторы. Например, взять лишь некоторые элементы (filter), преобразовать каждый элемент (map), посчитать сумму элементов или объединить всё в один объект (reduce).

Операторы можно разделить на две группы:
- Промежуточные (intermediate) — обрабатывают поступающие элементы и возвращают стрим. Промежуточных операторов в цепочке обработки элементов может быть много.
- Терминальные (terminal) — обрабатывают элементы и завершают работу стрима, так что терминальный оператор в цепочке может быть только один.
2. Получение объекта Stream
Пока что хватит теории. Пришло время посмотреть, как создать или получить объект java.util.stream.Stream.
- Пустой стрим: Stream.empty() // Stream<String>
- Стрим из List: list.stream() // Stream<String>
- Стрим из Map: map.entrySet().stream() // Stream<Map.Entry<String, String>>
- Стрим из массива: Arrays.stream(array) // Stream<String>
- Стрим из указанных элементов: Stream.of("a", "b", "c") // Stream<String>
А вот и пример:
- public static void main(String[] args) {
- List<String> list = Arrays.stream(args)
- .filter(s -> s.length() <= 2)
- .collect(Collectors.toList());
- }
В данном примере источником служит метод Arrays.stream, который из массива args делает стрим. Промежуточный оператор filter отбирает только те строки, длина которых не превышает два. Терминальный оператор collect собирает полученные элементы в новый список.
И ещё один пример:
- IntStream.of(120, 410, 85, 32, 314, 12)
- .filter(x -> x < 300)
- .map(x -> x + 11)
- .limit(3)
- .forEach(System.out::print)
десь уже три промежуточных оператора:
- filter — отбирает элементы, значение которых меньше 300,
- map — прибавляет 11 к каждому числу,
- limit — ограничивает количество элементов до 3.
Терминальный оператор forEach применяет функцию print к каждому приходящему элементу.
На ранних версиях Java этот пример выглядел бы так:
- int[] arr = {120, 410, 85, 32, 314, 12};
- int count = 0;
- for (int x : arr) {
- if (x >= 300) continue;
- x += 11;
- count++;
- if (count > 3) break;
- System.out.print(x);
- }
С увеличением числа операторов код в ранних версиях усложнялся бы на порядок, не говоря уже о том, что разбить вычисления на несколько потоков при таком подходе было бы крайне непросто.
3. Как работает стрим
У стримов есть некоторые особенности. Во-первых, обработка не начнётся до тех пор, пока не будет вызван терминальный оператор. list.stream().filter(x -> x > 100); не возьмёт ни единого элемента из списка. Во-вторых, стрим после обработки нельзя переиспользовать.
- Stream<String> stream = list.stream();
- stream.forEach(System.out::println);
- stream.filter(s -> s.contains("Stream API"));
- stream.forEach(System.out::println);
Код на второй строке выполнится, а вот на третьей выбросит исключение java.lang.IllegalStateException: stream has already been operated upon or closed.
Исходя из первой особенности, делаем вывод, что обработка происходит от терминального оператора к источнику. Это действительно так и это удобно. Мы можем в качестве источника использовать генерируемую бесконечную последовательность, скажем, факториала или чисел Фибоначчи, но обрабатывать лишь некоторую её часть
КПока мы не присоединили терминальный оператор, доступа к источнику не проводилось. Как только появился терминальный оператор forEach, он стал запрашивать элементы у стоящего перед ним оператора limit. Тот в свою очередь обращается к map, map к filter, а filter уже обращается к источнику. Затем элементы поступают в прямом порядке: источник, filter, map, limit и forEach.
Пока какой-либо из операторов не обработает элемент должным образом, новые запрошены не будут.
Как только через оператор limit прошло 3 элемента, он переходит в закрытое состояние и больше не будет запрашивать элементы у map. forEach запрашивает очередной элемент, но limit сообщает, что больше не может поставить элементов, поэтому forEach делает вывод, что элементы закончились и прекращает работу.
Такой подход зовётся pull iteration, то есть элементы запрашиваются у источника по мере надобности. К слову, в RxJava реализован push iteration подход, то есть источник сам уведомляет, что появились элементы и их нужно обработать.
4. Параллельные стримы
Стримы бывают последовательными (sequential) и параллельными (parallel). Последовательные выполняются только в текущем потоке, а вот параллельные используют общий пулForkJoinPool.commonPool(). При этом элементы разбиваются (если это возможно) на несколько групп и обрабатываются в каждом потоке отдельно. Затем на нужном этапе группы объединяются в одну для предоставления конечного результата.
Чтобы получить параллельный стрим, нужно либо вызвать метод parallelStream() вместо stream(), либо превратить обычный стрим в параллельный, вызвав промежуточный оператор parallel.
- list.parallelStream()
- .filter(x -> x > 10)
- .map(x -> x * 2)
- .collect(Collectors.toList());
- IntStream.range(0, 10)
- .parallel()
- .map(x -> x * 10)
- .sum();
Работа с потоконебезопасными коллекциями, разбиение элементов на части, создание потоков, объединение частей воедино, всё это кроется в реализации Stream API. От нас лишь требуется вызвать нужный метод и проследить, чтобы функции в операторах не зависели от каких-либо внешних факторов, иначе есть риск получить неверный результат или ошибку.
Вот так делать нельзя:
- final List<Integer> ints = new ArrayList<>();
- IntStream.range(0, 1000000)
- .parallel()
- .forEach(i -> ints.add(i));
- System.out.println(ints.size());
Это код Шрёдингера. Он может нормально выполниться и показать 1000000, может выполниться и показать 869877, а может и упасть с ошибкой Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 332 at java.util.ArrayList.add(ArrayList.java:459).
Поэтому разработчики настоятельно просят воздержаться от побочных эффектов в лямбдах, то тут, то там говоря в документации о невмешательстве (non-interference).
5. Стримы для примитивов
Кроме объектных стримов Stream<T>, существуют специальные стримы для примитивных типов:
- IntStream для int,
- LongStream для long,
- DoubleStream для double.
Для boolean, byte, short и char специальных стримов не придумали, но вместо них можно использовать IntStream, а затем приводить к нужному типу. Для float тоже придётся воспользоваться DoubleStream.
Примитивные стримы полезны, так как не нужно тратить время на боксинг/анбоксинг, к тому же у них есть ряд специальных операторов, упрощающих жизнь. Их мы рассмотрим очень скоро.
6. Операторы Stream API
Дальше приводятся операторы Stream API с описанием, демонстрацией и примерами. Можете использовать это как справочник.
6.1. Источники
empty()
Стрим, как и коллекция, может быть пустым, а значит всем последующем операторам нечего будет обрабатывать.- Stream.empty()
- .forEach(System.out::println);
- // Вывода нет
of(T value)
of(T... values)
Стрим для одного или нескольких перечисленных элементов. Очень часто вижу, что используют такую конструкцию:- Arrays.asList(1, 2, 3).stream()
- .forEach(System.out::println);
- Stream.of(1, 2, 3)
- .forEach(System.out::println);
ofNullable(T t)
Появился в Java 9. Возвращает пустой стрим, если в качестве аргумента передан null, в противном случае, возвращает стрим из одного элемента.- String str = Math.random() > 0.5 ? "I'm feeling lucky" : null;
- Stream.ofNullable(str)
- .forEach(System.out::println);
generate(Supplier s)
Возвращает стрим с бесконечной последовательностью элементов, генерируемых функцией Supplier s.
-
Stream.generate(() -> 6)
-
.limit(6)
-
.forEach(System.out::println);
-
// 6, 6, 6, 6, 6, 6
- Stream.generate(() -> 6)
- .limit(6)
- .forEach(System.out::println);
- // 6, 6, 6, 6, 6, 6
Поскольку стрим бесконечный, нужно его ограничивать или осторожно использовать, дабы не попасть в бесконечный цикл.
iterate(T seed, UnaryOperator f)
Возвращает бесконечный стрим с элементами, которые образуются в результате последовательного применения функции f к итерируемому значению. Первым элементом будет seed, затем f(seed), затем f(f(seed)) и так далее.- Stream.iterate(2, x -> x + 6)
- .limit(6)
- .forEach(System.out::println);
- // 2, 8, 14, 20, 26, 32
- Stream.iterate(1, x -> x * 2)
- .limit(6)
- .forEach(System.out::println);
- // 1, 2, , , , 32
iterate(T seed, Predicate hasNext, UnaryOperator f)
Появился в Java 9. Всё то же самое, только добавляется ещё один аргумент hasNext: если он возвращает false, то стрим завершается. Это очень похоже на цикл for:- for (i = seed; hasNext(i); i = f(i)) {
- }
- Stream.iterate(2, x -> x < 25, x -> x + 6)
- .forEach(System.out::println);
- // 2, 8, 14, 20
- Stream.iterate(4, x -> x < 100, x -> x * 4)
- .forEach(System.out::println);
- // , 16,
concat(Stream a, Stream b)
Объединяет два стрима так, что вначале идут элементы стрима A, а по его окончанию последуют элементы стрима B.- Stream.concat(
- Stream.of(1, 2, 3),
- Stream.of(4, 5, 6))
- .forEach(System.out::println);
- // 1, 2, 3, 4, 5, 6
- Stream.concat(
- Stream.of(10),
- Stream.of(, ))
- .forEach(System.out::println);
- // 10, 4, 16
builder()
Создаёт мутабельный объект для добавления элементов в стрим без использования какого-либо контейнера для этого.- Stream.Builder<Integer> streamBuider = Stream.<Integer>builder()
- .add(0)
- .add(1);
- for (int i = 2; i <= 8; i += 2) {
- streamBuider.accept(i);
- }
- streamBuider
- .add(9)
- .add(10)
- .build()
- .forEach(System.out::println);
- // 0, 1, 2, 4, 6, 8, 9, 10
IntStream.range(int startInclusive, int endExclusive)
LongStream.range(long startInclusive, long endExclusive)
Создаёт стрим из числового промежутка [start..end), то есть от start (включительно) по end.- IntStream.range(0, 10)
- .forEach(System.out::println);
- // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
- LongStream.range(-10L, -5L)
- .forEach(System.out::println);
- // -10, -9, -8, -7, -6
IntStream.rangeClosed(int startInclusive, int endInclusive)
LongStream.rangeClosed(long startInclusive, long endInclusive)
Создаёт стрим из числового промежутка [start..end], то есть от start (включительно) по end (включительно).- IntStream.rangeClosed(0, 5)
- .forEach(System.out::println);
- // 0, 1, 2, 3, 4, 5
- LongStream.range(-8L, -5L)
- .forEach(System.out::println);
- // -8, -7, -6, -5
6.2. Промежуточные операторы
filter(Predicate predicate)
Фильтрует стрим, принимая только те элементы, которые удовлетворяют заданному условию.- Stream.of(1, 2, 3)
- .filter(x -> x == 10)
- .forEach(System.out::print);
- // Вывода нет, так как после фильтрации стрим станет пустым
- Stream.of(120, 410, 85, 32, 314, 12)
- .filter(x -> x > 100)
- .forEach(System.out::println);
- // 120, 410, 314
- IntStream.range(2, 9)
- .filter(x -> x % == 0)
- .forEach(System.out::println);
- // 3, 6
map(Function mapper)
Применяет функцию к каждому элементу и затем возвращает стрим, в котором элементами будут результаты функции. map можно применять для изменения типа элементов.Stream.mapToDouble(ToDoubleFunction mapper)
Stream.mapToInt(ToIntFunction mapper)
Stream.mapToLong(ToLongFunction mapper)
IntStream.mapToObj(IntFunction mapper)
IntStream.mapToLong(IntToLongFunction mapper)
IntStream.mapToDouble(IntToDoubleFunction mapper)
Специальные операторы для преобразования объектного стрима в примитивный, примитивного в объектный, либо примитивного стрима одного типа в примитивный стрим другого.
- Stream.of("3", "4", "5")
- .map(Integer::parseInt)
- .map(x -> x + 10)
- .forEach(System.out::println);
- // 13, 14, 15
- Stream.of(120, 410, 85, 32, 314, 12)
- .map(x -> x + 11)
- .forEach(System.out::println);
- // 131, 421, 96, 43, 325, 23
- Stream.of("10", "11", "")
- .map(x -> Integer.parseInt(x, 16))
- .forEach(System.out::println);
- // , , 50
flatMap(Function<T, Stream<R>> mapper)
Один из самых интересных операторов. Работает как map, но с одним отличием — можно преобразовать один элемент в ноль, один или множество других.flatMapToDouble(Function mapper)
flatMapToInt(Function mapper)
flatMapToLong(Function mapper)
Как и в случае с map, служат для преобразования в примитивный стрим.
Для того, чтобы один элемент преобразовать в ноль элементов, нужно вернуть null, либо пустой стрим. Чтобы преобразовать в один элемент, нужно вернуть стрим из одного элемента, например, через Stream.of(x). Для возвращения нескольких элементов, можно любыми способами создать стрим с этими элементами.
- Stream.of(2, 3, 0, 1, 3)
- .flatMap(x -> IntStream.range(0, x))
- .forEach(System.out::println);
- // 0, 1, 0, 1, 2, 0, 0, 1, 2
- Stream.of(1, 2, 3, 4, 5, 6)
- .flatMap(x -> {
- switch (x % ) {
- case 0:
- return Stream.of(x, x*x, x*x*);
- case 1:
- return Stream.of(x);
- case 2:
- default:
- return Stream.empty();
- }
- })
- .forEach(System.out::println);
- // 1, 3, 9, 18, 4, 6, 36, 72
limit(long maxSize)
Ограничивает стрим maxSize элементами.- Stream.of(120, 410, 85, 32, 314, 12)
- .limit(4)
- .forEach(System.out::println);
- // 120, 410, 85, 32
- Stream.of(120, 410, 85, 32, 314, 12)
- .limit()
- .limit(5)
- .forEach(System.out::println);
- // 120, 410
- Stream.of(19)
- .limit()
- .forEach(System.out::println);
- // Вывода нет
skip(long n)
Пропускает n элементов стрима.- Stream.of(5, 10)
- .skip(40)
- .forEach(System.out::println);
- // Вывода нет
- Stream.of(120, 410, 85, 32, 314, 12)
- .skip(2)
- .forEach(System.out::println);
- // 85, 32, 314, 12
- IntStream.range(0, 10)
- .limit(5)
- .skip(3)
- .forEach(System.out::println);
- // ,
- IntStream.range(0, 10)
- .skip(5)
- .limit(3)
- .skip(1)
- .forEach(System.out::println);
- // ,
sorted()
sorted(Comparator comparator)
Сортирует элементы стрима. Причём работает этот оператор очень хитро: если стрим уже помечен как отсортированный, то сортировка проводиться не будет, иначе соберёт все элементы, отсортирует их и вернёт новый стрим, помеченный как отсортированный. См. 9.1.- IntStream.range(0, 100000000)
- .sorted()
- .limit(3)
- .forEach(System.out::println);
- // 0, 1, 2
- IntStream.concat(
- IntStream.range(0, 100000000),
- IntStream.of(-1, -2))
- .sorted()
- .limit(3)
- .forEach(System.out::println);
- // Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
- Stream.of(120, 410, 85, 32, 314, 12)
- .sorted()
- .forEach(System.out::println);
- // 12, 32, 85, 120, 314, 410
- Stream.of(120, 410, 85, 32, 314, 12)
- .sorted(Comparator.Order())
- .forEach(System.out::println);
- // 410, 314, 120, 85, 32, 12
distinct()
Убирает повторяющиеся элементы и возвращаем стрим с уникальными элементами. Как и в случае с sorted, смотрит, состоит ли уже стрим из уникальных элементов и если это не так, отбирает уникальные и помечает стрим как содержащий уникальные элементы.- Stream.of(2, 1, 8, 1, 3, 2)
- .distinct()
- .forEach(System.out::println);
- // 2, 1, 8, 3
- IntStream.concat(
- IntStream.range(2, 5),
- IntStream.range(0, 4))
- .distinct()
- .forEach(System.out::println);
- // , , , ,
peek(Consumer action)
Выполняет действие над каждым элементом стрима и при этом возвращает стрим с элементами исходного стрима. Служит для того, чтобы передать элемент куда-нибудь, не разрывая при этом цепочку операторов (вы же помните, что forEach — терминальный оператор и после него стрим завершается?), либо для отладки.- Stream.of(0, 3, 0, 0, 5)
- .peek(x -> System.out.format("before distinct: %d%n", x))
- .distinct()
- .peek(x -> System.out.format("after distinct: %d%n", x))
- .map(x -> x * x)
- .forEach(x -> System.out.format("after map: %d%n", x));
- // before distinct: 0
- // after distinct: 0
- // after map: 0
- // before distinct: 3
- // after distinct: 3
- // after map: 9
- // before distinct: 1
- // after distinct: 1
- // after map: 1
- // before distinct: 5
- // before distinct: 0
- // before distinct: 5
- // after distinct: 5
- // after map: 25
takeWhile(Predicate predicate)
Появился в Java 9. Возвращает элементы до тех пор, пока они удовлетворяют условию, то есть функция-предикат возвращает true. Это как limit, только не с числом, а с условием.- Stream.of(1, 2, 3, 4, 2, 5)
- .takeWhile(x -> x < 3)
- .forEach(System.out::println);
- // 1, 2
- IntStream.range(2, 7)
- .takeWhile(x -> x != )
- .forEach(System.out::println);
- // 2, 3, 4
dropWhile(Predicate predicate)
Появился в Java 9. Пропускает элементы до тех пор, пока они удовлетворяют условию, затем возвращает оставшуюся часть стрима. Если предикат вернул для первого элемента false, то ни единого элемента не будет пропущено. Оператор подобен skip, только работает по условию.- Stream.of(1, 2, 3, 4, 2, 5)
- .dropWhile(x -> x >= 3)
- .forEach(System.out::println);
- // 1, 2, 3, 4, 2, 5
- Stream.of(1, 2, 3, 4, 2, 5)
- .dropWhile(x -> x < 3)
- .forEach(System.out::println);
- // 3, 4, 2, 5
- IntStream.range(2, 7)
- .dropWhile(x -> x < )
- .forEach(System.out::println);
- // 5, 6
- IntStream.of(1, 3, 2, 0, 5, 4)
- .dropWhile(x -> x 2 == 1)
- .forEach(System.out::println);
- // 2, 0, 5, 6
boxed()
Преобразует примитивный стрим в объектный.- DoubleStream.of(0.1, Math.PI)
- .boxed()
- .map(Object::getClass)
- .forEach(System.out::println);
- // class java.lang.Double
- // class java.lang.Double
6.3. Терминальные операторы
void forEach(Consumer action)
Выполняет указанное действие для каждого элемента стрима.- Stream.of(120, 410, 85, 32, 314, 12)
- .forEach(x -> System.out.format("%s, ", x));
- // 120, 410, 85, 32, 314, 12
void forEachOrdered(Consumer action)
Тоже выполняет указанное действие для каждого элемента стрима, но перед этим добивается правильного порядка вхождения элементов. Используется для параллельных стримов, когда нужно получить правильную последовательность элементов.- IntStream.range(0, 100000)
- .parallel()
- .filter(x -> x % 10000 == 0)
- .map(x -> x / 10000)
- .forEach(System.out::println);
- // 5, 6, 7, 3, 4, 8, 0, 9, 1, 2
- IntStream.range(0, 100000)
- .parallel()
- .filter(x -> x % 10000 == 0)
- .map(x -> x / 10000)
- .forEachOrdered(System.out::println);
- // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
long count()
Возвращает количество элементов стрима.- long count = IntStream.range(0, 10)
- .flatMap(x -> IntStream.range(0, x))
- .count();
- System.out.println(count);
- // 45
- System.out.println(
- IntStream.rangeClosed(-3, )
- .count()
- );
- // 10
- System.out.println(
- Stream.of(0, 2, 9, 13, 5, 11)
- .(x -> x 2)
- .filter(x -> x % 2 == 1)
- .count()
- );
- // 0
R collect(Collector collector)
Один из самых мощных операторов Stream API. С его помощью можно собрать все элементы в список, множество или другую коллекцию, сгруппировать элементы по какому-нибудь критерию, объединить всё в строку и т.д.. В классе java.util.stream.Collectors очень много методов на все случаи жизни, мы рассмотрим их позже. При желании можно написать свой коллектор, реализовав интерфейс Collector.- List<Integer> list = Stream.of(1, 2, 3)
- .collect(Collectors.toList());
- // list: [1, 2, 3]
- String s = Stream.of(1, 2, 3)
- .map(String::valueOf)
- .collect(Collectors.joining("-", "<", ">"));
- // s: "<1-2-3>"
R collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
То же, что и collect(collector), только параметры разбиты для удобства. Если нужно быстро сделать какую-то операцию, нет нужды реализовывать интерфейс Collector, достаточно передать три лямбда-выражения.supplier должен поставлять новые объекты (контейнеры), например new ArrayList(), accumulator добавляет элемент в контейнер, combiner необходим для параллельных стримов и объединяет части стрима воедино.
- List<String> list = Stream.of("a", "b", "c", "d")
- .collect(ArrayList::new, ArrayList::add, ArrayList::addAll);
- // list: ["a", "b", "c", "d"]
Object[] toArray()
Возвращает нетипизированный массив с элементами стрима.A[] toArray(IntFunction<A[]> generator)
Аналогично, только возвращает типизированный массив.
- String[] elements = Stream.of("a", "b", "c", "d")
- .toArray(String[]::new);
- // elements: ["a", "b", "c", "d"]
T reduce(T identity, BinaryOperator accumulator)
U reduce(U identity, BiFunction accumulator, BinaryOperator combiner)
Ещё один полезный оператор. Позволяет преобразовать все элементы стрима в один объект. Например, посчитать сумму всех элементов, либо найти минимальный элемент.Сперва берётся объект identity и первый элемент стрима, применяется функция accumulator и identity становится её результатом. Затем всё продолжается для остальных элементов.
- int sum = Stream.of(1, 2, 3, 4, 5)
- .reduce(10, (acc, x) -> acc + x);
- // sum: 25
Optional reduce(BinaryOperator accumulator)
Этот метод отличается тем, что у него нет начального объекта identity. В качестве него служит первый элемент стрима. Поскольку стрим может быть пустой и тогда identity объект не присвоится, то результатом функции служит Optional, позволяющий обработать и эту ситуацию, вернув Optional.empty().- Optional<Integer> result = Stream.<Integer>empty()
- .reduce((acc, x) -> acc + x);
- System.out.println(result.isPresent());
- // false
- Optional<Integer> sum = Stream.of(1, 2, 3, 4, 5)
- .reduce((acc, x) -> acc + x);
- System.out.println(sum.get());
- // 15
- int sum = IntStream.of(2, 4, 6, 8)
- .reduce(, (acc, x) -> acc + x);
- // sum: 25
- int product = IntStream.range(0, 10)
- .filter(x -> x++ % 4 == 0)
- .reduce((acc, x) -> acc * x)
- .getAsInt();
- // product:
Optional min(Comparator comparator)
Optional max(Comparator comparator)
Поиск минимального/максимального элемента, основываясь на переданном компараторе. Внутри вызывается reduce:- reduce((a, b) -> comparator.compare(a, b) <= 0 ? a : b));
- reduce((a, b) -> comparator.compare(a, b) >= 0 ? a : b));
- int min = Stream.of(20, 11, 45, 78, 13)
- .min(Integer::compare).get();
- // min: 11
- int max = Stream.of(20, 11, 45, 78, 13)
- .max(Integer::compare).get();
- // max: 78
Optional findAny()
Возвращает первый попавшийся элемент стрима. В параллельных стримах это может быть действительно любой элемент, который лежал в разбитой части последовательности.Optional findFirst()
Гарантированно возвращает первый элемент стрима, даже если стрим параллельный.Если нужен любой элемент, то для параллельных стримов быстрее будет работать findAny().
- int anySeq = IntStream.range(4, 65536)
- .findAny()
- .getAsInt();
- // anySeq: 4
- int firstSeq = IntStream.range(4, 65536)
- .findFirst()
- .getAsInt();
- // firstSeq: 4
- int anyParallel = IntStream.range(4, 65536)
- .parallel()
- .findAny()
- .getAsInt();
- // anyParallel: 32770
- int firstParallel = IntStream.range(4, 65536)
- .parallel()
- .findFirst()
- .getAsInt();
- // firstParallel: 4
boolean allMatch(Predicate predicate)
Возвращает true, если все элементы стрима удовлетворяют условию predicate. Если встречается какой-либо элемент, для которого результат вызова функции-предиката будет false, то оператор перестаёт просматривать элементы и возвращает false.- boolean result = Stream.of(1, 2, 3, 4, 5)
- .allMatch(x -> x <= 7);
- // result: true
- boolean result = Stream.of(1, 2, 3, 4, 5)
- .allMatch(x -> x < 3);
- // result: false
- boolean result = Stream.of(120, 410, 85, 32, 314, 12)
- .allMatch(x -> x % 2 == 0);
- // result:
boolean anyMatch(Predicate predicate)
Возвращает true, если хотя бы один элемент стрима удовлетворяет условию predicate. Если такой элемент встретился, нет смысла продолжать перебор элементов, поэтому сразу возвращается результат.- boolean result = Stream.of(1, 2, 3, 4, 5)
- .anyMatch(x -> x == 3);
- // result: true
- boolean result = Stream.of(1, 2, 3, 4, 5)
- .anyMatch(x -> x == 8);
- // result: false
- boolean result = Stream.of(120, 410, 85, 32, 314, 12)
- .anyMatch(x -> x % 22 == 0);
- // result:
boolean noneMatch(Predicate predicate)
Возвращает true, если, пройдя все элементы стрима, ни один не удовлетворил условию predicate. Если встречается какой-либо элемент, для которого результат вызова функции-предиката будет true, то оператор перестаёт перебирать элементы и возвращает false.- boolean result = Stream.of(1, 2, 3, 4, 5)
- .noneMatch(x -> x == 9);
- // result: true
оператор перестаёт перебирать элементы и возвращает false.
- boolean result = Stream.of(1, 2, 3, 4, 5)
- .noneMatch(x -> x == 9);
- // result: true
- boolean result = Stream.of(1, 2, 3, 4, 5)
- .noneMatch(x -> x == 3);
- // result: false
ьььь
Комментариев нет:
Отправить комментарий