P2 04 Java8 5 StreamsAPI Ua
P2 04 Java8 5 StreamsAPI Ua
Stream API
• Stream - A sequence of elements supporting
sequential and parallel aggregate operations
languages.stream()
.filter((s) -> s.length() < 5)
.map(String::toUpperCase)
.sorted()
.forEach(System.out::println);
Stream API
• No storage
– A stream is not a data structure that stores elements; instead, it conveys elements from a
source such as a data structure, an array, a generator function, or an I/O channel, through a
pipeline of computational operations.
• Functional in nature
– An operation on a stream produces a result, but does not modify its source. For example,
filtering a Stream obtained from a collection produces a new Stream without the filtered
elements, rather than removing elements from the source collection.
• Laziness-seeking
– Many stream operations, such as filtering, mapping, or duplicate removal, can be
implemented lazily, exposing opportunities for optimization. For example, "find the first String
with three consecutive vowels" need not examine all the input strings. Stream operations are
divided into intermediate (Stream-producing) operations and terminal (value- or side-effect-
producing) operations. Intermediate operations are always lazy.
• Possibly unbounded
– While collections have a finite size, streams need not. Short-circuiting operations such as
limit(n) or findFirst() can allow computations on infinite streams to complete in finite time.
• Consumable
– The elements of a stream are only visited once during the life of a stream. Like an Iterator, a
new stream must be generated to revisit the same elements of the source.
Stream Data Types
• Stream<T>
• IntStream
• LongStream
• DoubleStream
* Примітка: Пригадайте
функціональні інтерфейси
Pipeline
• Джерело: створення/отримання стріма (1)
• Проміжні операції (0..n)
– стрім на вході
– стрім на виході
• Термінальна операція (1)
– стрім на вході
– на виході або нічього або результат (не стрім)
Pipeline - Приклад
public static void main(String[] args) {
}
Створення стрімів
• From a Collection via the stream() and parallelStream() methods
IntStream.range(5, 10).forEach(System.out::println);
System.out.println("Hi");
IntStream.iterate(0, i -> i + 1)
.filter(i -> i % 2 == 0);
System.out.println("Bye");
System.out.println("Hi again");
IntStream.iterate(0, i -> i + 1)
.filter(i -> i % 2 == 0)
.forEach(i -> {});
System.out.println("Bye again");
Проміжні операції
• Стрім на «вході» – стрім на «виході»
Stream<String> s1 = Stream.of("#4", "#11", "#41", "#999");
Stream<String> s2 = s1.map(s -> s.substring(1));
IntStream s3 = s2.mapToInt(Integer::parseInt);
IntStream s4 = s3.map(i -> i + 1);
Stream<String> s5 = s4.mapToObj(i -> "#" + i);
s5.forEach(System.out::println);
IntStream.range(1, 10)
.map(i -> i + 1)
.map(i -> i * 2)
.map(i -> i % 3)
.forEach(System.out::println);
Проміжні операції
• Stateless / Stateful
– Stateless: filter(), map(),…
• Наступні операції не залежать від попередніх
• Дуже добре масштабуються
– Stateful: distinct(), sorted(), …
• Наступні операції залежать від попередніх
• Можуть вимагати багато RAM або CPU
• Short-circuiting
– limit(), skip()
• Також є термінальні short-circuit операції, наприклад
findFirst()
Проміжні операції
• filter()
• map()
• flatMap()
• sorted()
• distinct()
• limit()
• skip()
• peek()
• sequential(), parallel(), unordered()
filter()
Stream<T> filter(Predicate<? super T> predicate)
IntStream
IntStream map(IntUnaryOperator mapper)
LongStream mapToLong(IntToLongFunction mapper)
DoubleStream mapToDouble(IntToDoubleFunction mapper)
<U> Stream<U> mapToObj(IntFunction<? extends U> mapper)
LongStream
….
DoubleStream
….
map()
IntStream
IntStream flatMap(IntFunction<? extends IntStream> mapper)
LongStream
LongStream flatMap(LongFunction<? extends LongStream> mapper)
DoubleStream
DoubleStream flatMap(DoubleFunction<? extends DoubleStream> mapper)
flatMap()
Stream.of("Java is a cool programming language",
"Python is cool too")
.flatMap(s -> Arrays.stream(s.split(" ")))
.forEach(System.out::println);
IntStream.of(3, 2, 2)
.flatMap(i -> IntStream.range(1, i+1))
.forEach(System.out::println);
sorted()
Stream<T>
Stream<T> sorted()
Stream<T> sorted(Comparator<? super T> comparator)
IntStream
IntStream sorted()
LongStream
LongStream sorted()
DoubleStream
DoubleStream sorted()
sorted()
Stream.of("Java is a cool programming language",
"Python is cool too")
.flatMap(s -> Arrays.stream(s.split(" ")))
.sorted()
.forEach(System.out::println);
Stream.of(1, 2, 3, 1, 2, 5)
.distinct()
.forEach(System.out::println);
limit()
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.limit(5)
.forEach(System.out::println);
skip()
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.skip(5)
.forEach(System.out::println);
limit() + skip()
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.skip(5)
.limit(5)
?
.forEach(System.out::println);
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
.limit(5)
.skip(5)
.forEach(System.out::println);
peek()
Stream<T>
Stream<T> peek(Consumer<? super T> action)
IntStream
IntStream peek(IntConsumer action)
LongStream
LongStream peek(LongConsumer action)
DoubleStream
DoubleStream peek(DoubleConsumer action)
peek()
Stream.of(1, 2, 3, 4, 5, 6)
.peek(i -> System.out.println("Peek before filter: " + i))
.filter(i -> i % 2 == 0)
.peek(i -> System.out.println("Peek after filter : " + i))
.forEach(i -> System.out.println("For Each : " + i));
Stream.of(1, 2, 3, 4, 5, 6)
?
.peek(i -> System.out.println("Peek before filter: " + i))
.filter(i -> i % 2 == 0)
.peek(i -> System.out.println("Peek after filter : " + i));
sequential(), parallel(), unordered()
• Можуть суттєво вплинути на швидкодію
Характеристики стрімів
• Ледащі
– до виклика термінальної операції нічого не
відбувається
• Одноразові
– Можуть бути використані тільки один раз
• Послідовні / паралельні
– Collection.parallelStream(), Stream.parallel()
• Впорядковані / невпорядковані
– із ordered можна зробити unordered для
підвищення ефективності (Stream.unordered())
Терминальные операции
• Прості
– forEach, forEachOrdered
– min, max, count
– average, sum (для числових)
– allMatch, anyMatch
– findAny, findFirst
• Трошки складніші ☺
– reduce (immutable reduction)
– collect (mutable reduction)
reduce
reduce(
U identity,
<U> U
BiFunction<U,? super T,U> accumulator,
BinaryOperator<U> combiner)
Приклад reduce 1
int sum = IntStream.range(1, 6)
.reduce((x,y)->x+y)
.orElse(-1);
System.out.println(sum);
Приклад reduce 2
int sum = IntStream.range(1, 6)
.reduce(0, (x,y)->x+y);
System.out.println(sum);
Приклад reduce 3 (map-reduce)
public class Emp {
String ename;
int sal;
String ename;
int sal;