Streams in java with example

Interface Stream

A sequence of elements supporting sequential and parallel aggregate operations. The following example illustrates an aggregate operation using Stream and IntStream :

 int sum = widgets.stream() .filter(w -> w.getColor() == RED) .mapToInt(w -> w.getWeight()) .sum(); 

In this example, widgets is a Collection . We create a stream of Widget objects via Collection.stream() , filter it to produce a stream containing only the red widgets, and then transform it into a stream of int values representing the weight of each red widget. Then this stream is summed to produce a total weight.

In addition to Stream , which is a stream of object references, there are primitive specializations for IntStream , LongStream , and DoubleStream , all of which are referred to as «streams» and conform to the characteristics and restrictions described here.

To perform a computation, stream operations are composed into a stream pipeline. A stream pipeline consists of a source (which might be an array, a collection, a generator function, an I/O channel, etc), zero or more intermediate operations (which transform a stream into another stream, such as filter(Predicate) ), and a terminal operation (which produces a result or side-effect, such as count() or forEach(Consumer) ). Streams are lazy; computation on the source data is only performed when the terminal operation is initiated, and source elements are consumed only as needed.

A stream implementation is permitted significant latitude in optimizing the computation of the result. For example, a stream implementation is free to elide operations (or entire stages) from a stream pipeline — and therefore elide invocation of behavioral parameters — if it can prove that it would not affect the result of the computation. This means that side-effects of behavioral parameters may not always be executed and should not be relied upon, unless otherwise specified (such as by the terminal operations forEach and forEachOrdered ). (For a specific example of such an optimization, see the API note documented on the count() operation. For more detail, see the side-effects section of the stream package documentation.)

Читайте также:  Профессиональное программирование на php шлосснейгл д

Collections and streams, while bearing some superficial similarities, have different goals. Collections are primarily concerned with the efficient management of, and access to, their elements. By contrast, streams do not provide a means to directly access or manipulate their elements, and are instead concerned with declaratively describing their source and the computational operations which will be performed in aggregate on that source. However, if the provided stream operations do not offer the desired functionality, the BaseStream.iterator() and BaseStream.spliterator() operations can be used to perform a controlled traversal.

A stream pipeline, like the «widgets» example above, can be viewed as a query on the stream source. Unless the source was explicitly designed for concurrent modification (such as a ConcurrentHashMap ), unpredictable or erroneous behavior may result from modifying the stream source while it is being queried.

  • must be non-interfering (they do not modify the stream source); and
  • in most cases must be stateless (their result should not depend on any state that might change during execution of the stream pipeline).

Such parameters are always instances of a functional interface such as Function , and are often lambda expressions or method references. Unless otherwise specified these parameters must be non-null.

A stream should be operated on (invoking an intermediate or terminal stream operation) only once. This rules out, for example, «forked» streams, where the same source feeds two or more pipelines, or multiple traversals of the same stream. A stream implementation may throw IllegalStateException if it detects that the stream is being reused. However, since some stream operations may return their receiver rather than a new stream object, it may not be possible to detect reuse in all cases.

Streams have a BaseStream.close() method and implement AutoCloseable . Operating on a stream after it has been closed will throw IllegalStateException . Most stream instances do not actually need to be closed after use, as they are backed by collections, arrays, or generating functions, which require no special resource management. Generally, only streams whose source is an IO channel, such as those returned by Files.lines(Path) , will require closing. If a stream does require closing, it must be opened as a resource within a try-with-resources statement or similar control structure to ensure that it is closed promptly after its operations have completed.

Stream pipelines may execute either sequentially or in parallel. This execution mode is a property of the stream. Streams are created with an initial choice of sequential or parallel execution. (For example, Collection.stream() creates a sequential stream, and Collection.parallelStream() creates a parallel one.) This choice of execution mode may be modified by the BaseStream.sequential() or BaseStream.parallel() methods, and may be queried with the BaseStream.isParallel() method.

Источник

Stream API

Java-университет

Stream API — это новый способ работать со структурами данных в функциональном стиле. Stream (поток) API (описание способов, которыми одна компьютерная программа может взаимодействовать с другой программой) — это по своей сути поток данных. Сам термин «поток» довольно размыт в программировании в целом и в Java в частности.

Stream API - 1

С появлением Java 8 Stream API позволило программистам писать существенно короче то, что раньше занимало много строк кода, а именно — упростить работу с наборами данных, в частности, упростить операции фильтрации, сортировки и другие манипуляции с данными. Если у вас промежуточных операций нет, часто можно и нужно обойтись без стрима, иначе код будет сложнее чем без потока.

Stream API - 2

C чего, собственно, начать? С создания экземпляра Stream, который опирается на нужную нам коллекцию, массив или метод их и откуда соответственно будут браться данные:

 List list = new ArrayList(); list.add("One"); list.add("Two"); list.add("Three"); list.add("Four"); list.add("Five"); list.add("Six"); list.add("Seven"); list.add("Eight"); list.add("Nine"); list.add("Ten"); Stream stream = list.stream(); 
 IntStream.of(50, 60, 70, 80, 90, 100, 110, 120).filter(x -> x < 90).map(x ->x + 10) .limit(3).forEach(System.out::print); 
 int[] arr = = 90) continue; x += 10; count++; if (count > 3) break; System.out.print(x); > 

Stream API - 3

  • Пустой стрим: Stream.empty()
  • Стрим из List: list.stream()
  • Стрим из Map: map.entrySet().stream()
  • Стрим из массива: Arrays.stream(array)
  • Стрим из указанных элементов: Stream.of(«1», «2», «3»)
  • Промежуточные (“intermediate”, ещё называют “lazy”) — обрабатывают поступающие элементы и возвращают стрим. Промежуточных операторов в цепочке обработки элементов может быть много.
  • Терминальные (“terminal”, ещё называют “eager”) — обрабатывают элементы и завершают работу стрима, так что терминальный оператор в цепочке может быть только один.
 1.List list = new ArrayList(); 2.list.add("One"); … 11.list.add("Ten"); 12.Stream stream = list.stream(); 13.stream.filter(x-> x.toString().length() == 3).forEach(System.out::println); 
  • 1 — создаём список list ;
  • 2-11 — заполняем его тестовыми данными;
  • 12 — создаём обьект Stream ;
  • 13 — метод filter (фильтр) — промежуточный оператор, x приравнивается к одному элементу коллекции для перебора (как при for each ) и после -> мы указываем как фильтруется наша коллекция и так как это промежуточный оператор, отфильтрованная коллекция идёт дальше в метод forEach который в свою очередь является терминальным (конечным) аналогом перебора for each (Выражение System.out::println сокращенно от: x-> System.out.println(x)) , которое в свою очередь проходит по всем элементам переданной ему коллекции и выводит её)

Stream API - 5

  • Обработка не начнётся до тех пор, пока не будет вызван терминальный оператор. list.stream().filter(s -> s > 5) (не возьмёт ни единого элемента из списка);
  • Экземпляр, стрима нельзя использовать более одного раза =( ;

Stream API - 6

 list.stream().filter(x-> x.toString().length() == 3).forEach(System.out::println); list.stream().forEach(x -> System.out.println(x)); 
 stream.filter(x-> x.toString().length() == 3).map(x -> x + " - the length of the letters is three").forEach(x -> System.out.println(x)); 

Stream API - 7

  • filter(Predicate predicate) фильтрует стрим, пропуская только те элементы, что проходят по условию (Predicate встроенный функциональный интерфейс, добавленный в Java SE 8 в пакет java.util.function . Проверяет значение на “true” и “false”);
  • map(Function mapper) даёт возможность создать функию с помощью которой мы будем изменять каждый элемент и пропускать его дальше (Функциональный интерфейс Function представляет функцию перехода от объекта типа T к объекту типа R)
  • flatMap(Function> mapper) — как и в случае с map , служат для преобразования в примитивный стрим.
 String[] array = ; Stream streamOfArray = Arrays.stream(array); streamOfArray.map(s->s.split("")) //Преобразование слова в массив букв .flatMap(Arrays::stream).distinct() //выравнивает каждый сгенерированный поток в один поток .collect(Collectors.toList()).forEach(System.out::println); 

В то время когда map преобразует в список потоков (точнее потоков) [stream1,stream2,stream3,stream4] =>Stream.of(stream1,stream2,stream3,stream4) :

 String[] array = ; Stream streamOfArray = Arrays.stream(array); streamOfArray.map(s->s.split("")) //Преобразование слова в массив букв .map(Arrays::stream).distinct() //Сделать массив в отдельный поток .collect(Collectors.toList()).forEach(System.out::println); 
  • flatMapToDouble(Function mapper)
  • flatMapToInt(Function mapper)
  • flatMapToLong(Function mapper)
 Stream.of(2, 3, 0, 1, 3) .flatMapToInt(x -> IntStream.range(0, x)) .forEach(System.out::print);// 010120012 
 Stream.of(2, 3, 0, 1, 3) .map(x -> IntStream.range(0, x)) .forEach(System.out::print);//перечень стримов(потоков); 
 stream.limit(5).forEach(x -> System.out.println(x)); 
 stream.skip(3).forEach(x -> System.out.println(x)); 
 stream.sorted().forEach(x -> System.out.println(x)); 
 Predicate isPositive = x -> x > 0; System.out.println(isPositive.test(3)); // true System.out.println(isPositive.test(-9)); // false 

Stream API - 8

  • forEach(Consumer action) – аналог for each (Consumer выполняет некоторое действие над объектом типа T, при этом ничего не возвращая);
  • count() – возвращает количество елементов стрима: System.out.println(stream.count());
  • collect(Collector collector) – метод собирает все элементы в список, множество или другую коллекцию, сгруппировывает элементы по какому-нибудь критерию, объединяет всё в строку и т.д.:
 List list = Stream.of(“One”, “Two”, “Three”).collect(Collectors.toList()); 
 int sum = Stream.of(1, 2, 3, 4, 5).reduce(10, (acc, x) -> acc + x);// = 25 
 Stream.of(1, 2, 3, 4, 9).findFirst(); 
 Stream.of(1, 2, 3, 4, 9).allMatch(x -> x  
 Stream.of(1, 2, 3, 4, 9).anyMatch(x -> x >= 7);//true 
 Stream.of(1, 2, 3, 4, 9).noneMatch(x -> x >= 7);//false 
 List list = Stream.of(99, 2, 3).collect(Collectors.toList()); 
 Set set = Stream.of(99, 2, 3).collect(Collectors.toSet()); 
 Long count = Stream.of("1", "2", "3", "4").collect(Collectors.counting()); 
 String a = Stream.of("s", "u" ,"p", "e", "r").collect(Collectors.joining()); System.out.println(a); // super String b = Stream.of("s", "u", "p", "e", "r").collect(Collectors.joining("-")); System.out.println(b); // s-u-p-e-r String c = Stream.of("s", "u", "p", "e", "r").collect(Collectors.joining(" -> ", "[ ", " ]")); System.out.println(c); // [ s -> u -> p -> e -> r ] 

Источник

Оцените статью