What is Stream API?
The Stream API is a new way to work with data structures in a functional style. A Stream API (a description of the ways in which one computer program can communicate with another program) is, at its core, a stream of data. The term "thread" itself is quite vague in programming in general and in Java in particular.List<String> list = new ArrayList<String>();
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();
As mentioned above, the Stream API allows you to reduce the number of lines of code. Example with a 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);
Example without thread:
int[] arr = {50, 60, 70, 80, 90, 100, 110, 120
int count = 0;
for (int x : arr) {
if (x >= 90) continue;
x += 10;
count++;
if (count > 3) break;
System.out.print(x);
}
Possible ways to create a Stream:
- Empty stream:
Stream.empty()
- Stream from List:
list.stream()
- Stream from Map:
map.entrySet().stream()
- Stream from the array:
Arrays.stream(array)
- Stream from the specified elements:
Stream.of("1", "2", "3")
- Intermediate (also called “lazy”) - process incoming elements and return the stream. There can be many intermediate operators in the element processing chain.
- Terminal (“terminal”, also called “eager”) - process elements and terminate the stream, so there can only be one terminal operator in the chain.
1.List<String> list = new ArrayList<String>();
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);
What's going on here:
- 1 - create a list
list
; - 2-11 - fill it with test data;
- 12 - create an object
Stream
; - 13 - method
filter
(filter) - intermediate operator,x
equates to one element of the collection for enumeration (as withfor each
) and after -> we indicate how our collection is filtered and since this is an intermediate operator, the filtered collection goes further into the method,forEach
which in turn is terminal (final) analogue of enumerationfor each
(ExpressionSystem.out::println
short for:,x-> System.out.println(x))
which in turn goes through all the elements of the collection passed to it and displays it)
- Processing will not begin until the terminal operator is called.
list.stream().filter(s -> s > 5)
(will not take a single element from the list); - An instance of a stream cannot be used more than once =( ;
Therefore, every time it’s new:
list.stream().filter(x-> x.toString().length() == 3).forEach(System.out::println);
list.stream().forEach(x -> System.out.println(x));
There can be many intermediate operators called on one stream, while there is only one terminal operator:
stream.filter(x-> x.toString().length() == 3).map(x -> x + " - the length of the letters is three").forEach(x -> System.out.println(x));
filter(Predicate predicate)
filters the stream, passing only those elements that pass the condition (Predicate is a built-in functional interface added to the package in Java SE 8.java.util.function
Checks the value for “ true ” and “ false ”);map(Function mapper)
makes it possible to create a function with which we will change each element and skip it further (The functional interfaceFunction<T,R>
represents the function of transition from an object of type T to an object of type R)flatMap(Function<T, Stream<R>> mapper)
- as in the case withmap
, they are used to convert to a primitive stream.
[stream1,stream2,stream3,stream4] => stream
:
String[] array = {"Java", "Ruuuuussshhh"};
Stream<String> streamOfArray = Arrays.stream(array);
streamOfArray.map(s->s.split("")) //Convert the word to an array of letters
.flatMap(Arrays::stream).distinct() //aligns each generated thread into a single thread
.collect(Collectors.toList()).forEach(System.out::println);
While map
it converts to a list of threads (more precisely <Stream>
threads) [stream1,stream2,stream3,stream4] =>Stream.of(stream1,stream2,stream3,stream4)
:
String[] array = {"Java", "Ruuuuussshhh"};
Stream<String> streamOfArray = Arrays.stream(array);
streamOfArray.map(s->s.split("")) //Convert the word to an array of letters
.map(Arrays::stream).distinct() //Make the array into a separate thread
.collect(Collectors.toList()).forEach(System.out::println);
Another difference compared to map
, you can convert one element to zero, one or many others. In order to convert one element into zero elements, you need to return null
, or an empty stream. To convert to one element, you need to return a stream from one element, for example, via Stream.of(x)
. To return several elements, you can create a stream with these elements by any means. The same flatMap method, but for Double, Integer and Long:
- 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
-
IntStream.range(0,x) – outputs elements from 0 (inclusive) to x (not inclusive) to the stream;
map:
Stream.of(2, 3, 0, 1, 3) .map(x -> IntStream.range(0, x)) .forEach(System.out::print);//list of streams (streams);
-
limit(long maxSize) – limits the stream by the number of elements:
stream.limit(5).forEach(x -> System.out.println(x));
-
skip(long n) – skip n elements:
stream.skip(3).forEach(x -> System.out.println(x));
-
sorted()
- sorted(Comparator comparator) – sorts the stream (sorting like TreeMap):
stream.sorted().forEach(x -> System.out.println(x));
-
distinct() — checks the stream for uniqueness of elements (removes repetitions of elements);
-
dropWhile(Predicate predicate) - skips elements that satisfy the condition (appeared in java 9, The Predicate<T> functional interface checks whether some condition is met. If it is met, then true is returned. The lambda expression takes an object of type T as a parameter:
Predicate<Integer> isPositive = x -> x > 0; System.out.println(isPositive.test(3)); // true System.out.println(isPositive.test(-9)); // false
-
forEach(Consumer action) – analogue of for each (Consumer<T> performs some action on an object of type T, without returning anything);
-
count() – returns the number of stream elements:
System.out.println(stream.count());
-
collect(Collector collector) – method collects all elements into a list, set or other collection, groups elements according to some criterion, combines everything into a string, etc.:
List<String> list = Stream.of(“One”, “Two”, “Three”).collect(Collectors.toList());
-
collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
— the same as ,collect(collector)
only the parameters are broken down for convenience (supplier
supplies new objects (containers), for examplenew ArrayList()
,accumulator
adds an element to the container,combiner
combines parts of the stream together); -
reduce(T identity, BinaryOperator accumulator) - converts all elements of the stream into one object (calculate the sum of all elements, or find the minimum element), first take the object
identity
and the first element of the stream, apply the functionaccumulator
andidentity
become its result. Then everything continues for the remaining elements.int sum = Stream.of(1, 2, 3, 4, 5).reduce(10, (acc, x) -> acc + x);// = 25
-
reduce(BinaryOperator accumulator)
— the same method as above but the initial one is missingidentity
, it is the first element of the streamOptional min(Comparator comparator)
Optional max(Comparator comparator) searches for the minimum/maximum element based on the passed comparator; -
findFirst()
– pulls out the first element of the stream:Stream.of(1, 2, 3, 4, 9).findFirst();
-
allMatch(Predicate predicate)
— returns true if all elements of the stream satisfy the condition. If any element is encountered for which the result of calling the predicate function is false , then the operator stops scanning the elements and returns false :Stream.of(1, 2, 3, 4, 9).allMatch(x -> x <= 7);//false
-
anyMatch(Predicate predicate)
— will return true if at least one element of the stream satisfies the conditionpredicate
:Stream.of(1, 2, 3, 4, 9).anyMatch(x -> x >= 7);//true
-
noneMatch(Predicate predicate)
— will return true if, having gone through all the elements of the stream, none of them satisfied the conditionpredicate
:Stream.of(1, 2, 3, 4, 9).noneMatch(x -> x >= 7);//false
Collectors
:
-
toList()
— collects elements intoList
:List<Integer> list = Stream.of(99, 2, 3).collect(Collectors.toList());
-
toSet()
— collects elements into a set:Set<Integer> set = Stream.of(99, 2, 3).collect(Collectors.toSet());
-
counting()
— Counts the number of elements:Long count = Stream.of("1", "2", "3", "4").collect(Collectors.counting());
-
joining()
-
joining(CharSequence delimiter)
-
joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
— collects elements into one line. Additionally, you can specify a separator, as well as a prefix and suffix for the entire sequence: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 ]
-
summingInt(ToIntFunction mapper)
-
summingLong(ToLongFunction mapper)
-
summingDouble(ToDoubleFunction mapper)
- a collector that converts objects to int/long/double and calculates the sum.
GO TO FULL VERSION