SlideShare une entreprise Scribd logo
1  sur  68
Stream API: рекомендации
лучших собаководов
Тагир Валеев
Институт систем информатики СО РАН
1
Что это за чувак на сцене?
https://github.com/amaembo/streamex
2
Что это за чувак на сцене?
• JDK-8072727 Add variation of Stream.iterate() that's finite
• JDK-8136686 Collectors.counting can use Collectors.summingLong to reduce boxing
• JDK-8141630 Specification of Collections.synchronized* need to state traversal constraints
• JDK-8145007 Pattern splitAsStream is not late binding as required by the specification
• JDK-8146218 Add LocalDate.datesUntil method producing Stream<LocalDate>
• JDK-8147505 BaseStream.onClose() should not allow registering new handlers after stream is consumed
• JDK-8148115 Stream.findFirst for unordered source optimization
• JDK-8148250 Stream.limit() parallel tasks with ordered non-SUBSIZED source should short-circuit
• JDK-8148838 Stream.flatMap(...).spliterator() cannot properly split after tryAdvance()
3
Что это за чувак на сцене?
4
5
source.stream()
6
.map(x -> x.squash())
7
.filter(x -> x.getColor() != YELLOW)
8
.forEach(System.out::println)
9
source.stream()
.map(x -> x.squash())
.filter(x -> x.getColor() != YELLOW)
.forEach(System.out::println)
10
AtomicLong cnt = new AtomicLong();
.peek(x -> cnt.incrementAndGet())
11
AtomicLong cnt = new AtomicLong();
source.stream()
.map(x -> x.squash())
.peek(x -> cnt.incrementAndGet())
.filter(x -> x.getColor() != YELLOW)
.forEach(System.out::println)
12
Источники
(source)
Переходы
(intermediate operation)
Сливы
(terminal operation)
13
Источники
14
Задача №1:
Сделать источник дочерних узлов для заданного родительского
DOM XML узла.
15
Задача №1:
Сделать источник дочерних узлов для заданного родительского
DOM XML узла.
public static Stream<Node> children(Node parent) {
NodeList nodeList = parent.getChildNodes();
return IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item);
}
16
Задача №1:
Сделать источник дочерних узлов для заданного родительского
DOM XML узла.
public static Stream<Node> children(Node parent) {
NodeList nodeList = parent.getChildNodes();
return IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item);
}
Random.ints()
Random.longs()
String.chars()
Files.lines()
Files.list()
LocalDate.datesUntil()
Process.descendants()
ProcessHandle.allProcesses()
NetworkInterface.inetAddresses()
NetworkInterface.subInterfaces()
17
Задача №2:
Сделать источник элементов списка вместе с индексами.
public class IndexedValue<T> {
public final int index;
public final T value;
public IndexedValue(int index, T value) {
this.index = index;
this.value = value;
}
}
public static <T> Stream<IndexedValue<T>> withIndices(List<T> list) {
return IntStream.range(0, list.size())
.mapToObj(idx -> new IndexedValue<>(idx, list.get(idx)));
}
18
Задача №3:
Сделать источник пользователей в существующем классе Group.
public class Group {
private User[] users;
public Stream<User> users() {
return Arrays.stream(users);
}
}
public class Group {
private Map<String, User> nameToUser;
public Stream<User> users() {
return nameToUser.values().stream();
}
}
public class Group {
private List<User> users;
public Stream<User> users() {
return users.stream();
}
}
19
Задача №4:
Сделать источник, генерирующий декартово произведение списков строк.
List<List<String>> input = asList(asList("a", "b", "c"),
asList("x", "y"), asList("1", "2", "3"));
>> ax1
>> ax2
>> ax3
>> ay1
>> ay2
...
>> cy2
>> cy3
20
Задача №4:
Сделать источник, генерирующий декартово произведение списков строк.
List<List<String>> input = asList(asList("a", "b", "c"),
asList("x", "y"), asList("1", "2", "3"));
Stream<String> stream =
input.get(0).stream().flatMap(a ->
input.get(1).stream().flatMap(b ->
input.get(2).stream().map(c -> a + b + c)));
stream.forEach(System.out::println);
>> ax1
>> ax2
>> ax3
>> ay1
...
21
Задача №4:
Сделать источник, генерирующий декартово произведение списков строк.
List<List<String>> input = asList(asList("a", "b", "c"),
asList("x", "y"), asList("1", "2", "3"));
Supplier<Stream<String>> s = input.stream()
// Stream<List<String>>
.<Supplier<Stream<String>>>map(list -> list::stream)
// Stream<Supplier<Stream<String>>>
.reduce((sup1, sup2) -> () -> sup1.get()
.flatMap(e1 -> sup2.get().map(e2 -> e1+e2)))
// Optional<Supplier<Stream<String>>>
.orElse(() -> Stream.of(""));
s.get().forEach(System.out::println);
22
Промежуточные
операции
23
Задача №5:
Выбрать из стрима все элементы заданного класса.
IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item)
.???
24
Задача №5:
Выбрать из стрима все элементы заданного класса.
25
IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item)
.filter(node -> node instanceof Element);
IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item)
.filter(Element.class::isInstance);
Задача №5:
Выбрать из стрима все элементы заданного класса.
26
IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item)
.filter(node -> node instanceof Element)
.map(node -> (Element)node);
IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item)
.filter(Element.class::isInstance)
.map(Element.class::cast);
Задача №5:
Выбрать из стрима все элементы заданного класса.
27
public static <T, TT> Stream<TT> select(Stream<T> stream, Class<TT> clazz) {
return stream.filter(clazz::isInstance).map(clazz::cast);
}
select(IntStream
.range(0, nodeList.getLength())
.mapToObj(nodeList::item),
Element.class)
.forEach(e -> System.out.println(e.getTagName()));
28
Задача №5:
Выбрать из стрима все элементы заданного класса.
29
public static <T, TT> Function<T, Stream<TT>> select(Class<TT> clazz) {
return e -> clazz.isInstance(e) ? Stream.of(clazz.cast(e)) : null;
}
IntStream.range(0, nodeList.getLength())
.mapToObj(nodeList::item)
.flatMap(select(Element.class))
.forEach(e -> System.out.println(e.getTagName()));
Задача №5:
Выбрать из стрима все элементы заданного класса.
30
IntStreamEx.range(nodeList.getLength())
.mapToObj(nodeList::item)
.select(Element.class)
.forEach(e -> System.out.println(e.getTagName()));
Задача №6:
Оставить значения, которые повторяются не менее n раз.
31
List<String> list = Arrays.asList("JPoint", "Joker", "JBreak",
"JBreak", "Joker", "JBreak");
Map<String, Long> counts = list.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
counts.values().removeIf(cnt -> cnt < 3);
counts.keySet().forEach(System.out::println);
>> JBreak
Задача №6:
Оставить значения, которые повторяются не менее n раз.
32
public static <T> Predicate<T> distinct(long atLeast) {
Map<T, Long> map = new ConcurrentHashMap<>();
return t -> map.merge(t, 1L, Long::sum) == atLeast;
}
List<String> list = Arrays.asList("JPoint", "Joker", "JBreak",
"JBreak", "Joker", "JBreak");
list.stream().filter(distinct(3)).forEach(System.out::println);
>> JBreak
Задача №7:
Реализовать takeWhile: прервать Stream по условию
33
public static <T> Predicate<T> takeWhile(Predicate<T> predicate) {
AtomicBoolean matched = new AtomicBoolean();
return t -> {
if(matched.get())
return false;
if(!predicate.test(t)) {
matched.set(true);
return false;
}
return true;
};
}
Stream.of(1, 2, 3, -1, 4, 5, 6).filter(takeWhile(x -> x > 0))
.forEach(System.out::println);
Задача №7:
Реализовать takeWhile: прервать Stream по условию
34
public static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<T> predicate) {
Spliterator<T> src = stream.spliterator();
Spliterator<T> res = new Spliterators.AbstractSpliterator<T>(src.estimateSize(),
src.characteristics() & ~Spliterator.SIZED & ~Spliterator.SUBSIZED) {
boolean finished = false;
T next;
@Override
public boolean tryAdvance(Consumer<? super T> action) {
if (finished || !src.tryAdvance(t -> next = t) || !predicate.test(next)) {
finished = true;
return false;
}
action.accept(next);
return true;
}
};
return StreamSupport.stream(res, stream.isParallel()).onClose(stream::close);
}
Задача №7:
Реализовать takeWhile: прервать Stream по условию
35
takeWhile(new Random().ints().boxed(),
x -> x % 10 != 0)
.forEach(System.out::println);
IntStreamEx.of(new Random())
.boxed()
.takeWhile(x -> x % 10 != 0)
.forEach(System.out::println);
Терминальные
операции
36
Коллекторы
37
Коллекторы
38
Коллекторы
39
public interface Collector<T, A, R> {
Supplier<A> supplier();
BiConsumer<A, T> accumulator();
BinaryOperator<A> combiner();
Function<A, R> finisher();
Set<Characteristics> characteristics();
}
Задача №8:
Преобразовать List<Map<K, V>> в Map<K, List<V>>
40
Дано:
[{a=1, b=2},
{a=3, d=4, e=5},
{a=5, b=6, e=7}
]
Надо:
{a=[1, 3, 5],
b=[2, 6],
d=[4],
e=[5, 7]
}
Задача №8:
Преобразовать List<Map<K, V>> в Map<K, List<V>>
41
input.stream()
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
Задача №8:
Преобразовать List<Map<K, V>> в Map<K, List<V>>
42
input.stream()
.flatMap(map -> map.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey,
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
StreamEx.of(input)
.flatMapToEntry(m -> m)
.grouping();
Задача №8:
Преобразовать List<Map<K, V>> в Map<K, List<V>>
43
import static java.util.stream.Collectors.*;
input.stream()
.flatMap(map -> map.entrySet().stream())
.collect(groupingBy(Map.Entry::getKey,
mapping(Map.Entry::getValue,
toList())));
44
Стримоз (сущ., тж. стримомания) — патологическое
импульсивно возникающее стремление разместить всю
логику Java-программы или существенной её части в одном
Stream-конвейере, сопровождающееся непреодолимой
потребностью удовлетворить это стремление.
Задача №9:
Найти отделы с суммарной зарплатой всех сотрудников более
миллиона рублей, отсортировав по убыванию суммарной зарплаты.
45
interface Employee {
Department getDepartment();
long getSalary();
}
Задача №9:
Найти отделы с суммарной зарплатой всех сотрудников более
миллиона рублей, отсортировав по убыванию суммарной зарплаты.
46
Map<Department, Long> deptSalaries = employees.stream().collect(
groupingBy(Employee::getDepartment,
summingLong(Employee::getSalary)));
deptSalaries.entrySet().stream()
.filter(e -> e.getValue() > 1_000_000)
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue,
(a, b) -> a, LinkedHashMap::new));
Задача №9:
Найти отделы с суммарной зарплатой всех сотрудников более
миллиона рублей, отсортировав по убыванию суммарной зарплаты.
47
Map<Department, Long> deptSalaries = StreamEx.of(employees)
.groupingBy(Employee::getDepartment,
summingLong(Employee::getSalary));
EntryStream.of(deptSalaries)
.filterValues(salary -> salary > 1_000_000)
.reverseSorted(Map.Entry.comparingByValue())
.toCustomMap(LinkedHashMap::new);
Задача №9:
Найти отделы с суммарной зарплатой всех сотрудников более
миллиона рублей, отсортировав по убыванию суммарной зарплаты.
48
Map<Department, Long> result = employees.stream().collect(
collectingAndThen(groupingBy(Employee::getDepartment,
summingLong(Employee::getSalary)),
deptSalaries -> deptSalaries.entrySet().stream()
.filter(e -> e.getValue() > 1_000_000)
.sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.collect(toMap(Map.Entry::getKey, Map.Entry::getValue,
(a, b) -> a, LinkedHashMap::new))));
Не делайте так никогда!
Задача №10:
Найти все максимальные элементы по заданному компаратору.
49
Stream.of("JBreak", "JPoint", "Joker")
.collect(maxAll(Comparator.comparing(String::length)));
>> [JBreak, JPoint]
Задача №10:
Найти все максимальные элементы по заданному компаратору.
50
public static <T> Collector<T, ?, List<T>> maxAll(Comparator<T> cmp) {
BiConsumer<List<T>, T> accumulator = (list, t) -> {
if (!list.isEmpty()) {
int c = cmp.compare(list.get(0), t);
if (c > 0)
return;
if (c < 0)
list.clear();
}
list.add(t);
};
return Collector.of(ArrayList::new, accumulator, (l1, l2) -> {
l2.forEach(t -> accumulator.accept(l1, t));
return l1;
});
}
Задача №11:
Проверить, уникальны ли входные элементы (да или нет).
51
Stream.of("JUG.ru", "JBreak", "JPoint",
"Joker", "JFocus", "JavaOne", "JBreak")
.allMatch(ConcurrentHashMap.newKeySet()::add);
Задача №12:
Посчитать хэш-код строки стандартным алгоритмом:
52
"JBreak".hashCode();
>> -2111961387
"JBreak".chars().reduce(0, (a, b) -> a*31+b);
>> -2111961387
Задача №12:
Посчитать хэш-код строки стандартным алгоритмом:
53
"JBreak".hashCode();
>> -2111961387
"JBreak".chars().reduce(0, (a, b) -> a*31+b);
>> -2111961387
"JBreak".chars().parallel().reduce(0, (a, b) -> a*31+b);
>> 4473889
Задача №12:
Посчитать хэш-код строки стандартным алгоритмом:
54
"JBreak".hashCode();
>> -2111961387
"JBreak".chars().reduce(0, (a, b) -> a*31+b);
>> -2111961387
"JBreak".chars().parallel().reduce(0, (a, b) -> a*31+b);
>> 4473889
(a*31+b)*31+c != a*31+(b*31+c)
Задача №12:
Посчитать хэш-код строки стандартным алгоритмом:
55
public static int foldLeft(IntStream input, int seed,
IntBinaryOperator op) {
int[] box = { seed };
input.forEachOrdered(t -> box[0] = op.applyAsInt(box[0], t));
return box[0];
}
foldLeft("JBreak".chars().parallel(), 0, (a, b) -> a*31+b);
Любым способом
56
Задача №13:
Обработать перекрывающиеся пары из входного потока
57
List<String> input = Arrays.asList("A", "B", "C", "D", "E");
StreamEx.of(input)
.pairMap((a, b) -> a + " -> " + b)
.toList();
>> [A -> B, B -> C, C -> D, D -> E]
Задача №13:
Обработать перекрывающиеся пары из входного потока
58
List<String> input = Arrays.asList("A", "B", "C", "D", "E");
IntStream.range(0, input.size()-1)
.mapToObj(idx -> input.get(idx)+" -> "+input.get(idx+1))
.collect(Collectors.toList());
>> [A -> B, B -> C, C -> D, D -> E]
Задача №13:
Обработать перекрывающиеся пары из входного потока
59
List<String> input = Arrays.asList("A", "B", "C", "D", "E");
public static <T, R> Stream<R> pairs(List<T> input,
BiFunction<T, T, R> mapper) {
return IntStream.range(0, input.size()-1)
.mapToObj(idx ->
mapper.apply(input.get(idx), input.get(idx+1)));
}
pairs(input, (a, b) -> a + " -> " + b)
.collect(Collectors.toList());
>> [A -> B, B -> C, C -> D, D -> E]
Задача №13:
Обработать перекрывающиеся пары из входного потока
60
List<String> input = Arrays.asList("A", "B", "C", "D", "E");
List<String> result = new ArrayList<>();
input.stream().reduce((a, b) -> {
result.add(a+" -> "+b);
return b;
});
>> [A -> B, B -> C, C -> D, D -> E]
Не делайте так никогда!
Задача №13:
Обработать перекрывающиеся пары из входного потока
61
List<String> input = Arrays.asList("A", "B", "C", "D", "E");
String s = input.stream().map(a -> a+";"+a)
.collect(Collectors.joining(" -> "));
>> A;A -> B;B -> C;C -> D;D -> E;E
Pattern.compile(";").splitAsStream(s)
.filter(b -> b.contains(" -> "))
.collect(Collectors.toList());
>> [A -> B, B -> C, C -> D, D -> E]
Не делайте так никогда!
Задача №13:
Обработать перекрывающиеся пары из входного потока
62
static <T, TT, A, R> Collector<T, ?, R> pairs(BiFunction<T, T, TT> mapper,
Collector<TT, A, R> downstream) {
class Acc {
T first, last; A acc = downstream.supplier().get();
void add(T next) {
if(last == null) first = next;
else downstream.accumulator().accept(acc, mapper.apply(last, next));
last = next;
}
Acc combine(Acc other) {
downstream.accumulator().accept(acc, mapper.apply(last, other.first));
acc = downstream.combiner().apply(acc, other.acc);
last = other.last;
return this;
}
}
return Collector.of(Acc::new, Acc::add, Acc::combine,
acc -> downstream.finisher().apply(acc.acc));
}
Задача №14:
Разбить входной поток на группы равной длины
63
List<String> input = Arrays.asList
("a", "b", "c", "d", "e", "f", "g", "h");
>> [[a, b, c], [d, e, f], [g, h]]
Задача №14:
Разбить входной поток на группы равной длины
64
static <T> Stream<List<T>> ofSublists(List<T> list, int n) {
int size = list.size();
return IntStream.rangeClosed(0, (size-1) / n).mapToObj(idx ->
list.subList(idx * n, Math.min(size, idx * n + n)));
}
List<String> input = Arrays.asList
("a", "b", "c", "d", "e", "f", "g", "h");
List<List<String>> list = ofSublists(input, 3)
.map(ArrayList::new)
.collect(Collectors.toList());
>> [[a, b, c], [d, e, f], [g, h]]
Задача №15:
Разбить входной поток на группы, начинающиеся с данного элемента
65
List<String> input = Arrays.asList("Start", "a", "b", "c",
"Start", "d", "Start", "e", "f", "g", "h", "i", "Start");
StreamEx.of(input)
.groupRuns((a, b) -> !b.equals("Start")).toList();
>> [[Start, a, b, c], [Start, d], [Start, e, f, g, h, i], [Start]]
Задача №15:
Разбить входной поток на группы, начинающиеся с данного элемента
66
List<String> input = Arrays.asList("Start", "a", "b", "c",
"Start", "d", "Start", "e", "f", "g", "h", "i", "Start");
IntStream.rangeClosed(0, input.size())
.filter(idx -> idx == 0 || idx == input.size() ||
input.get(idx).equals("Start"))
.boxed().collect(pairs(input::subList, Collectors.toList()));
>> [[Start, a, b, c], [Start, d], [Start, e, f, g, h, i], [Start]]
Библиотеки
67
• jOOλ (by Lukas Eder)
• https://github.com/jOOQ/jOOL
• Cyclops-react (by John McClean)
• https://github.com/aol/cyclops-react
• Guava (FluentIterable)
• https://github.com/google/guava
• javaslang (by Daniel Dietrich)
• https://github.com/javaslang/javaslang
Спасибо за внимание
68
https://twitter.com/tagir_valeev
https://github.com/amaembo
https://habrahabr.ru/users/lany

Contenu connexe

Tendances

Мир Python функционалим с помощью библиотек
Мир Python  функционалим с помощью библиотекМир Python  функционалим с помощью библиотек
Мир Python функционалим с помощью библиотекPyNSK
 
JPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаJPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаAnton Arhipov
 
Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"LogeekNightUkraine
 
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...Ontico
 
Something about Golang
Something about GolangSomething about Golang
Something about GolangAnton Arhipov
 
Groovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всёмGroovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всёмRuslan Balkin
 
Игорь Лабутин «Коллекционируем данные в .NET»
Игорь Лабутин «Коллекционируем данные в .NET»Игорь Лабутин «Коллекционируем данные в .NET»
Игорь Лабутин «Коллекционируем данные в .NET»SpbDotNet Community
 
Школа-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с даннымиШкола-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с даннымиГлеб Тарасов
 
RDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на SwiftRDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на SwiftRAMBLER&Co
 
Оптимизация производительности Python
Оптимизация производительности PythonОптимизация производительности Python
Оптимизация производительности PythonPyNSK
 
Java осень 2014 занятие 7
Java осень 2014 занятие 7Java осень 2014 занятие 7
Java осень 2014 занятие 7Technopark
 
Yield at me 'cause I'm awaiting: асинхронные итераторы в C# 8
Yield at me 'cause I'm awaiting: асинхронные итераторы в C# 8Yield at me 'cause I'm awaiting: асинхронные итераторы в C# 8
Yield at me 'cause I'm awaiting: асинхронные итераторы в C# 8Andrey Karpov
 
Монады для барабанщиков. Антон Холомьёв
Монады для барабанщиков. Антон ХоломьёвМонады для барабанщиков. Антон Холомьёв
Монады для барабанщиков. Антон ХоломьёвЮрий Сыровецкий
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupMail.ru Group
 
RDSDataSource: Promises
RDSDataSource: PromisesRDSDataSource: Promises
RDSDataSource: PromisesRAMBLER&Co
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6Technopark
 
07 - Java. Элементы функционального программирования в Java
07 - Java. Элементы функционального программирования в Java07 - Java. Элементы функционального программирования в Java
07 - Java. Элементы функционального программирования в JavaRoman Brovko
 
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev FedorProgramming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev FedorFedor Lavrentyev
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в DjangoMoscowDjango
 

Tendances (20)

Мир Python функционалим с помощью библиотек
Мир Python  функционалим с помощью библиотекМир Python  функционалим с помощью библиотек
Мир Python функционалим с помощью библиотек
 
JPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчикаJPoint 2015 - Javassist на службе Java-разработчика
JPoint 2015 - Javassist на службе Java-разработчика
 
Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"Sergii Tsypanov "Performance 1001 Tips"
Sergii Tsypanov "Performance 1001 Tips"
 
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
Отказоустойчивая обработка 10M OAuth токенов на Tarantool / Владимир Перепели...
 
Something about Golang
Something about GolangSomething about Golang
Something about Golang
 
Groovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всёмGroovy и Grails. Быстро и обо всём
Groovy и Grails. Быстро и обо всём
 
Игорь Лабутин «Коллекционируем данные в .NET»
Игорь Лабутин «Коллекционируем данные в .NET»Игорь Лабутин «Коллекционируем данные в .NET»
Игорь Лабутин «Коллекционируем данные в .NET»
 
Scala on android
Scala on androidScala on android
Scala on android
 
Школа-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с даннымиШкола-студия разработки для iOS. Лекция 4. Работа с данными
Школа-студия разработки для iOS. Лекция 4. Работа с данными
 
RDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на SwiftRDSDataSource: Чистые тесты на Swift
RDSDataSource: Чистые тесты на Swift
 
Оптимизация производительности Python
Оптимизация производительности PythonОптимизация производительности Python
Оптимизация производительности Python
 
Java осень 2014 занятие 7
Java осень 2014 занятие 7Java осень 2014 занятие 7
Java осень 2014 занятие 7
 
Yield at me 'cause I'm awaiting: асинхронные итераторы в C# 8
Yield at me 'cause I'm awaiting: асинхронные итераторы в C# 8Yield at me 'cause I'm awaiting: асинхронные итераторы в C# 8
Yield at me 'cause I'm awaiting: асинхронные итераторы в C# 8
 
Монады для барабанщиков. Антон Холомьёв
Монады для барабанщиков. Антон ХоломьёвМонады для барабанщиков. Антон Холомьёв
Монады для барабанщиков. Антон Холомьёв
 
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru GroupКак не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
Как не сделать врагами архитектуру и оптимизацию, Кирилл Березин, Mail.ru Group
 
RDSDataSource: Promises
RDSDataSource: PromisesRDSDataSource: Promises
RDSDataSource: Promises
 
Java осень 2014 занятие 6
Java осень 2014 занятие 6Java осень 2014 занятие 6
Java осень 2014 занятие 6
 
07 - Java. Элементы функционального программирования в Java
07 - Java. Элементы функционального программирования в Java07 - Java. Элементы функционального программирования в Java
07 - Java. Элементы функционального программирования в Java
 
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev FedorProgramming Java - Lecture 02 - Objects - Lavrentyev Fedor
Programming Java - Lecture 02 - Objects - Lavrentyev Fedor
 
Производительность в Django
Производительность в DjangoПроизводительность в Django
Производительность в Django
 

En vedette

JPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream APIJPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream APItvaleev
 
Joker 2015 - Валеев Тагир - Что же мы измеряем?
Joker 2015 - Валеев Тагир - Что же мы измеряем?Joker 2015 - Валеев Тагир - Что же мы измеряем?
Joker 2015 - Валеев Тагир - Что же мы измеряем?tvaleev
 
Железные счётчики на страже производительности
Железные счётчики на страже производительностиЖелезные счётчики на страже производительности
Железные счётчики на страже производительностиSergey Kuksenko
 
"Quantum" Performance Effects
"Quantum" Performance Effects"Quantum" Performance Effects
"Quantum" Performance EffectsSergey Kuksenko
 
"Quantum" performance effects
"Quantum" performance effects"Quantum" performance effects
"Quantum" performance effectsSergey Kuksenko
 
Java 8 Puzzlers as it was presented at Codemash 2017
Java 8 Puzzlers as it was presented at Codemash 2017Java 8 Puzzlers as it was presented at Codemash 2017
Java 8 Puzzlers as it was presented at Codemash 2017Baruch Sadogursky
 
Java Performance: Speedup your application with hardware counters
Java Performance: Speedup your application with hardware countersJava Performance: Speedup your application with hardware counters
Java Performance: Speedup your application with hardware countersSergey Kuksenko
 

En vedette (9)

JPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream APIJPoint 2016 - Валеев Тагир - Странности Stream API
JPoint 2016 - Валеев Тагир - Странности Stream API
 
Joker 2015 - Валеев Тагир - Что же мы измеряем?
Joker 2015 - Валеев Тагир - Что же мы измеряем?Joker 2015 - Валеев Тагир - Что же мы измеряем?
Joker 2015 - Валеев Тагир - Что же мы измеряем?
 
JDK8: Stream style
JDK8: Stream styleJDK8: Stream style
JDK8: Stream style
 
Железные счётчики на страже производительности
Железные счётчики на страже производительностиЖелезные счётчики на страже производительности
Железные счётчики на страже производительности
 
"Quantum" Performance Effects
"Quantum" Performance Effects"Quantum" Performance Effects
"Quantum" Performance Effects
 
Javaland keynote final
Javaland keynote finalJavaland keynote final
Javaland keynote final
 
"Quantum" performance effects
"Quantum" performance effects"Quantum" performance effects
"Quantum" performance effects
 
Java 8 Puzzlers as it was presented at Codemash 2017
Java 8 Puzzlers as it was presented at Codemash 2017Java 8 Puzzlers as it was presented at Codemash 2017
Java 8 Puzzlers as it was presented at Codemash 2017
 
Java Performance: Speedup your application with hardware counters
Java Performance: Speedup your application with hardware countersJava Performance: Speedup your application with hardware counters
Java Performance: Speedup your application with hardware counters
 

Similaire à Stream API: рекомендации лучших собаководов

Работа с БД в Java
Работа с БД в JavaРабота с БД в Java
Работа с БД в Javametaform
 
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...JetBrains Russia
 
[Expert Fridays] Dmitry Isaev - Функциональные велосипеды в Java
[Expert Fridays] Dmitry Isaev - Функциональные велосипеды в Java[Expert Fridays] Dmitry Isaev - Функциональные велосипеды в Java
[Expert Fridays] Dmitry Isaev - Функциональные велосипеды в JavaProvectus
 
Перевод базы Caché из 8 бит в Unicode
Перевод базы Caché из 8 бит в UnicodeПеревод базы Caché из 8 бит в Unicode
Перевод базы Caché из 8 бит в UnicodeInterSystems
 
Functional Programming in Python
Functional Programming in PythonFunctional Programming in Python
Functional Programming in Pythondudarev
 
Java осень 2012 лекция 8
Java осень 2012 лекция 8Java осень 2012 лекция 8
Java осень 2012 лекция 8Technopark
 
RxJava + Retrofit
RxJava + RetrofitRxJava + Retrofit
RxJava + RetrofitDev2Dev
 
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)Ontico
 
Java осень 2013 лекция 8
Java осень 2013 лекция 8Java осень 2013 лекция 8
Java осень 2013 лекция 8Technopark
 
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...solit
 
8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)Smolensk Computer Science Club
 
TMPA-2013 Dmitry Zaitsev
TMPA-2013 Dmitry ZaitsevTMPA-2013 Dmitry Zaitsev
TMPA-2013 Dmitry ZaitsevIosif Itkin
 
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...Ivan Muratov
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actualYevgen Levik
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularizationIvan Krylov
 
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кодаРазвитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кодаPositive Hack Days
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6Technopark
 
Шаблоны проектирования 1
Шаблоны проектирования 1Шаблоны проектирования 1
Шаблоны проектирования 1Constantin Kichinsky
 

Similaire à Stream API: рекомендации лучших собаководов (20)

Java8. Innovations
Java8. InnovationsJava8. Innovations
Java8. Innovations
 
Работа с БД в Java
Работа с БД в JavaРабота с БД в Java
Работа с БД в Java
 
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
Разработка IntelliJ IDEA: впечатления новичка. Тагир Валеев, Senior Software ...
 
[Expert Fridays] Dmitry Isaev - Функциональные велосипеды в Java
[Expert Fridays] Dmitry Isaev - Функциональные велосипеды в Java[Expert Fridays] Dmitry Isaev - Функциональные велосипеды в Java
[Expert Fridays] Dmitry Isaev - Функциональные велосипеды в Java
 
Перевод базы Caché из 8 бит в Unicode
Перевод базы Caché из 8 бит в UnicodeПеревод базы Caché из 8 бит в Unicode
Перевод базы Caché из 8 бит в Unicode
 
Functional Programming in Python
Functional Programming in PythonFunctional Programming in Python
Functional Programming in Python
 
Java осень 2012 лекция 8
Java осень 2012 лекция 8Java осень 2012 лекция 8
Java осень 2012 лекция 8
 
RxJava + Retrofit
RxJava + RetrofitRxJava + Retrofit
RxJava + Retrofit
 
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
Денормализованное хранение данных в PostgreSQL 9.2 (Александр Коротков)
 
Java осень 2013 лекция 8
Java осень 2013 лекция 8Java осень 2013 лекция 8
Java осень 2013 лекция 8
 
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
Solit 2014, Реактивный Javascript. Победа над асинхронностью и вложенностью, ...
 
8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)8 встреча — Язык программирования Python (В. Ананьев)
8 встреча — Язык программирования Python (В. Ананьев)
 
Charming python sc2-8
Charming python sc2-8Charming python sc2-8
Charming python sc2-8
 
TMPA-2013 Dmitry Zaitsev
TMPA-2013 Dmitry ZaitsevTMPA-2013 Dmitry Zaitsev
TMPA-2013 Dmitry Zaitsev
 
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...Time series data in a relational database. TimescaleDB and PipelineDB extensi...
Time series data in a relational database. TimescaleDB and PipelineDB extensi...
 
Multithreading in java past and actual
Multithreading in java past and actualMultithreading in java past and actual
Multithreading in java past and actual
 
Java 9: what is there beyond modularization
Java 9: what is there beyond modularizationJava 9: what is there beyond modularization
Java 9: what is there beyond modularization
 
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кодаРазвитие технологий генерации эксплойтов на основе анализа бинарного кода
Развитие технологий генерации эксплойтов на основе анализа бинарного кода
 
Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 
Шаблоны проектирования 1
Шаблоны проектирования 1Шаблоны проектирования 1
Шаблоны проектирования 1
 

Stream API: рекомендации лучших собаководов

  • 1. Stream API: рекомендации лучших собаководов Тагир Валеев Институт систем информатики СО РАН 1
  • 2. Что это за чувак на сцене? https://github.com/amaembo/streamex 2
  • 3. Что это за чувак на сцене? • JDK-8072727 Add variation of Stream.iterate() that's finite • JDK-8136686 Collectors.counting can use Collectors.summingLong to reduce boxing • JDK-8141630 Specification of Collections.synchronized* need to state traversal constraints • JDK-8145007 Pattern splitAsStream is not late binding as required by the specification • JDK-8146218 Add LocalDate.datesUntil method producing Stream<LocalDate> • JDK-8147505 BaseStream.onClose() should not allow registering new handlers after stream is consumed • JDK-8148115 Stream.findFirst for unordered source optimization • JDK-8148250 Stream.limit() parallel tasks with ordered non-SUBSIZED source should short-circuit • JDK-8148838 Stream.flatMap(...).spliterator() cannot properly split after tryAdvance() 3
  • 4. Что это за чувак на сцене? 4
  • 5. 5
  • 10. source.stream() .map(x -> x.squash()) .filter(x -> x.getColor() != YELLOW) .forEach(System.out::println) 10
  • 11. AtomicLong cnt = new AtomicLong(); .peek(x -> cnt.incrementAndGet()) 11
  • 12. AtomicLong cnt = new AtomicLong(); source.stream() .map(x -> x.squash()) .peek(x -> cnt.incrementAndGet()) .filter(x -> x.getColor() != YELLOW) .forEach(System.out::println) 12
  • 15. Задача №1: Сделать источник дочерних узлов для заданного родительского DOM XML узла. 15
  • 16. Задача №1: Сделать источник дочерних узлов для заданного родительского DOM XML узла. public static Stream<Node> children(Node parent) { NodeList nodeList = parent.getChildNodes(); return IntStream.range(0, nodeList.getLength()) .mapToObj(nodeList::item); } 16
  • 17. Задача №1: Сделать источник дочерних узлов для заданного родительского DOM XML узла. public static Stream<Node> children(Node parent) { NodeList nodeList = parent.getChildNodes(); return IntStream.range(0, nodeList.getLength()) .mapToObj(nodeList::item); } Random.ints() Random.longs() String.chars() Files.lines() Files.list() LocalDate.datesUntil() Process.descendants() ProcessHandle.allProcesses() NetworkInterface.inetAddresses() NetworkInterface.subInterfaces() 17
  • 18. Задача №2: Сделать источник элементов списка вместе с индексами. public class IndexedValue<T> { public final int index; public final T value; public IndexedValue(int index, T value) { this.index = index; this.value = value; } } public static <T> Stream<IndexedValue<T>> withIndices(List<T> list) { return IntStream.range(0, list.size()) .mapToObj(idx -> new IndexedValue<>(idx, list.get(idx))); } 18
  • 19. Задача №3: Сделать источник пользователей в существующем классе Group. public class Group { private User[] users; public Stream<User> users() { return Arrays.stream(users); } } public class Group { private Map<String, User> nameToUser; public Stream<User> users() { return nameToUser.values().stream(); } } public class Group { private List<User> users; public Stream<User> users() { return users.stream(); } } 19
  • 20. Задача №4: Сделать источник, генерирующий декартово произведение списков строк. List<List<String>> input = asList(asList("a", "b", "c"), asList("x", "y"), asList("1", "2", "3")); >> ax1 >> ax2 >> ax3 >> ay1 >> ay2 ... >> cy2 >> cy3 20
  • 21. Задача №4: Сделать источник, генерирующий декартово произведение списков строк. List<List<String>> input = asList(asList("a", "b", "c"), asList("x", "y"), asList("1", "2", "3")); Stream<String> stream = input.get(0).stream().flatMap(a -> input.get(1).stream().flatMap(b -> input.get(2).stream().map(c -> a + b + c))); stream.forEach(System.out::println); >> ax1 >> ax2 >> ax3 >> ay1 ... 21
  • 22. Задача №4: Сделать источник, генерирующий декартово произведение списков строк. List<List<String>> input = asList(asList("a", "b", "c"), asList("x", "y"), asList("1", "2", "3")); Supplier<Stream<String>> s = input.stream() // Stream<List<String>> .<Supplier<Stream<String>>>map(list -> list::stream) // Stream<Supplier<Stream<String>>> .reduce((sup1, sup2) -> () -> sup1.get() .flatMap(e1 -> sup2.get().map(e2 -> e1+e2))) // Optional<Supplier<Stream<String>>> .orElse(() -> Stream.of("")); s.get().forEach(System.out::println); 22
  • 24. Задача №5: Выбрать из стрима все элементы заданного класса. IntStream.range(0, nodeList.getLength()) .mapToObj(nodeList::item) .??? 24
  • 25. Задача №5: Выбрать из стрима все элементы заданного класса. 25 IntStream.range(0, nodeList.getLength()) .mapToObj(nodeList::item) .filter(node -> node instanceof Element); IntStream.range(0, nodeList.getLength()) .mapToObj(nodeList::item) .filter(Element.class::isInstance);
  • 26. Задача №5: Выбрать из стрима все элементы заданного класса. 26 IntStream.range(0, nodeList.getLength()) .mapToObj(nodeList::item) .filter(node -> node instanceof Element) .map(node -> (Element)node); IntStream.range(0, nodeList.getLength()) .mapToObj(nodeList::item) .filter(Element.class::isInstance) .map(Element.class::cast);
  • 27. Задача №5: Выбрать из стрима все элементы заданного класса. 27 public static <T, TT> Stream<TT> select(Stream<T> stream, Class<TT> clazz) { return stream.filter(clazz::isInstance).map(clazz::cast); } select(IntStream .range(0, nodeList.getLength()) .mapToObj(nodeList::item), Element.class) .forEach(e -> System.out.println(e.getTagName()));
  • 28. 28
  • 29. Задача №5: Выбрать из стрима все элементы заданного класса. 29 public static <T, TT> Function<T, Stream<TT>> select(Class<TT> clazz) { return e -> clazz.isInstance(e) ? Stream.of(clazz.cast(e)) : null; } IntStream.range(0, nodeList.getLength()) .mapToObj(nodeList::item) .flatMap(select(Element.class)) .forEach(e -> System.out.println(e.getTagName()));
  • 30. Задача №5: Выбрать из стрима все элементы заданного класса. 30 IntStreamEx.range(nodeList.getLength()) .mapToObj(nodeList::item) .select(Element.class) .forEach(e -> System.out.println(e.getTagName()));
  • 31. Задача №6: Оставить значения, которые повторяются не менее n раз. 31 List<String> list = Arrays.asList("JPoint", "Joker", "JBreak", "JBreak", "Joker", "JBreak"); Map<String, Long> counts = list.stream() .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); counts.values().removeIf(cnt -> cnt < 3); counts.keySet().forEach(System.out::println); >> JBreak
  • 32. Задача №6: Оставить значения, которые повторяются не менее n раз. 32 public static <T> Predicate<T> distinct(long atLeast) { Map<T, Long> map = new ConcurrentHashMap<>(); return t -> map.merge(t, 1L, Long::sum) == atLeast; } List<String> list = Arrays.asList("JPoint", "Joker", "JBreak", "JBreak", "Joker", "JBreak"); list.stream().filter(distinct(3)).forEach(System.out::println); >> JBreak
  • 33. Задача №7: Реализовать takeWhile: прервать Stream по условию 33 public static <T> Predicate<T> takeWhile(Predicate<T> predicate) { AtomicBoolean matched = new AtomicBoolean(); return t -> { if(matched.get()) return false; if(!predicate.test(t)) { matched.set(true); return false; } return true; }; } Stream.of(1, 2, 3, -1, 4, 5, 6).filter(takeWhile(x -> x > 0)) .forEach(System.out::println);
  • 34. Задача №7: Реализовать takeWhile: прервать Stream по условию 34 public static <T> Stream<T> takeWhile(Stream<T> stream, Predicate<T> predicate) { Spliterator<T> src = stream.spliterator(); Spliterator<T> res = new Spliterators.AbstractSpliterator<T>(src.estimateSize(), src.characteristics() & ~Spliterator.SIZED & ~Spliterator.SUBSIZED) { boolean finished = false; T next; @Override public boolean tryAdvance(Consumer<? super T> action) { if (finished || !src.tryAdvance(t -> next = t) || !predicate.test(next)) { finished = true; return false; } action.accept(next); return true; } }; return StreamSupport.stream(res, stream.isParallel()).onClose(stream::close); }
  • 35. Задача №7: Реализовать takeWhile: прервать Stream по условию 35 takeWhile(new Random().ints().boxed(), x -> x % 10 != 0) .forEach(System.out::println); IntStreamEx.of(new Random()) .boxed() .takeWhile(x -> x % 10 != 0) .forEach(System.out::println);
  • 39. Коллекторы 39 public interface Collector<T, A, R> { Supplier<A> supplier(); BiConsumer<A, T> accumulator(); BinaryOperator<A> combiner(); Function<A, R> finisher(); Set<Characteristics> characteristics(); }
  • 40. Задача №8: Преобразовать List<Map<K, V>> в Map<K, List<V>> 40 Дано: [{a=1, b=2}, {a=3, d=4, e=5}, {a=5, b=6, e=7} ] Надо: {a=[1, 3, 5], b=[2, 6], d=[4], e=[5, 7] }
  • 41. Задача №8: Преобразовать List<Map<K, V>> в Map<K, List<V>> 41 input.stream() .flatMap(map -> map.entrySet().stream()) .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList())));
  • 42. Задача №8: Преобразовать List<Map<K, V>> в Map<K, List<V>> 42 input.stream() .flatMap(map -> map.entrySet().stream()) .collect(Collectors.groupingBy(Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList()))); StreamEx.of(input) .flatMapToEntry(m -> m) .grouping();
  • 43. Задача №8: Преобразовать List<Map<K, V>> в Map<K, List<V>> 43 import static java.util.stream.Collectors.*; input.stream() .flatMap(map -> map.entrySet().stream()) .collect(groupingBy(Map.Entry::getKey, mapping(Map.Entry::getValue, toList())));
  • 44. 44 Стримоз (сущ., тж. стримомания) — патологическое импульсивно возникающее стремление разместить всю логику Java-программы или существенной её части в одном Stream-конвейере, сопровождающееся непреодолимой потребностью удовлетворить это стремление.
  • 45. Задача №9: Найти отделы с суммарной зарплатой всех сотрудников более миллиона рублей, отсортировав по убыванию суммарной зарплаты. 45 interface Employee { Department getDepartment(); long getSalary(); }
  • 46. Задача №9: Найти отделы с суммарной зарплатой всех сотрудников более миллиона рублей, отсортировав по убыванию суммарной зарплаты. 46 Map<Department, Long> deptSalaries = employees.stream().collect( groupingBy(Employee::getDepartment, summingLong(Employee::getSalary))); deptSalaries.entrySet().stream() .filter(e -> e.getValue() > 1_000_000) .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new));
  • 47. Задача №9: Найти отделы с суммарной зарплатой всех сотрудников более миллиона рублей, отсортировав по убыванию суммарной зарплаты. 47 Map<Department, Long> deptSalaries = StreamEx.of(employees) .groupingBy(Employee::getDepartment, summingLong(Employee::getSalary)); EntryStream.of(deptSalaries) .filterValues(salary -> salary > 1_000_000) .reverseSorted(Map.Entry.comparingByValue()) .toCustomMap(LinkedHashMap::new);
  • 48. Задача №9: Найти отделы с суммарной зарплатой всех сотрудников более миллиона рублей, отсортировав по убыванию суммарной зарплаты. 48 Map<Department, Long> result = employees.stream().collect( collectingAndThen(groupingBy(Employee::getDepartment, summingLong(Employee::getSalary)), deptSalaries -> deptSalaries.entrySet().stream() .filter(e -> e.getValue() > 1_000_000) .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())) .collect(toMap(Map.Entry::getKey, Map.Entry::getValue, (a, b) -> a, LinkedHashMap::new)))); Не делайте так никогда!
  • 49. Задача №10: Найти все максимальные элементы по заданному компаратору. 49 Stream.of("JBreak", "JPoint", "Joker") .collect(maxAll(Comparator.comparing(String::length))); >> [JBreak, JPoint]
  • 50. Задача №10: Найти все максимальные элементы по заданному компаратору. 50 public static <T> Collector<T, ?, List<T>> maxAll(Comparator<T> cmp) { BiConsumer<List<T>, T> accumulator = (list, t) -> { if (!list.isEmpty()) { int c = cmp.compare(list.get(0), t); if (c > 0) return; if (c < 0) list.clear(); } list.add(t); }; return Collector.of(ArrayList::new, accumulator, (l1, l2) -> { l2.forEach(t -> accumulator.accept(l1, t)); return l1; }); }
  • 51. Задача №11: Проверить, уникальны ли входные элементы (да или нет). 51 Stream.of("JUG.ru", "JBreak", "JPoint", "Joker", "JFocus", "JavaOne", "JBreak") .allMatch(ConcurrentHashMap.newKeySet()::add);
  • 52. Задача №12: Посчитать хэш-код строки стандартным алгоритмом: 52 "JBreak".hashCode(); >> -2111961387 "JBreak".chars().reduce(0, (a, b) -> a*31+b); >> -2111961387
  • 53. Задача №12: Посчитать хэш-код строки стандартным алгоритмом: 53 "JBreak".hashCode(); >> -2111961387 "JBreak".chars().reduce(0, (a, b) -> a*31+b); >> -2111961387 "JBreak".chars().parallel().reduce(0, (a, b) -> a*31+b); >> 4473889
  • 54. Задача №12: Посчитать хэш-код строки стандартным алгоритмом: 54 "JBreak".hashCode(); >> -2111961387 "JBreak".chars().reduce(0, (a, b) -> a*31+b); >> -2111961387 "JBreak".chars().parallel().reduce(0, (a, b) -> a*31+b); >> 4473889 (a*31+b)*31+c != a*31+(b*31+c)
  • 55. Задача №12: Посчитать хэш-код строки стандартным алгоритмом: 55 public static int foldLeft(IntStream input, int seed, IntBinaryOperator op) { int[] box = { seed }; input.forEachOrdered(t -> box[0] = op.applyAsInt(box[0], t)); return box[0]; } foldLeft("JBreak".chars().parallel(), 0, (a, b) -> a*31+b);
  • 57. Задача №13: Обработать перекрывающиеся пары из входного потока 57 List<String> input = Arrays.asList("A", "B", "C", "D", "E"); StreamEx.of(input) .pairMap((a, b) -> a + " -> " + b) .toList(); >> [A -> B, B -> C, C -> D, D -> E]
  • 58. Задача №13: Обработать перекрывающиеся пары из входного потока 58 List<String> input = Arrays.asList("A", "B", "C", "D", "E"); IntStream.range(0, input.size()-1) .mapToObj(idx -> input.get(idx)+" -> "+input.get(idx+1)) .collect(Collectors.toList()); >> [A -> B, B -> C, C -> D, D -> E]
  • 59. Задача №13: Обработать перекрывающиеся пары из входного потока 59 List<String> input = Arrays.asList("A", "B", "C", "D", "E"); public static <T, R> Stream<R> pairs(List<T> input, BiFunction<T, T, R> mapper) { return IntStream.range(0, input.size()-1) .mapToObj(idx -> mapper.apply(input.get(idx), input.get(idx+1))); } pairs(input, (a, b) -> a + " -> " + b) .collect(Collectors.toList()); >> [A -> B, B -> C, C -> D, D -> E]
  • 60. Задача №13: Обработать перекрывающиеся пары из входного потока 60 List<String> input = Arrays.asList("A", "B", "C", "D", "E"); List<String> result = new ArrayList<>(); input.stream().reduce((a, b) -> { result.add(a+" -> "+b); return b; }); >> [A -> B, B -> C, C -> D, D -> E] Не делайте так никогда!
  • 61. Задача №13: Обработать перекрывающиеся пары из входного потока 61 List<String> input = Arrays.asList("A", "B", "C", "D", "E"); String s = input.stream().map(a -> a+";"+a) .collect(Collectors.joining(" -> ")); >> A;A -> B;B -> C;C -> D;D -> E;E Pattern.compile(";").splitAsStream(s) .filter(b -> b.contains(" -> ")) .collect(Collectors.toList()); >> [A -> B, B -> C, C -> D, D -> E] Не делайте так никогда!
  • 62. Задача №13: Обработать перекрывающиеся пары из входного потока 62 static <T, TT, A, R> Collector<T, ?, R> pairs(BiFunction<T, T, TT> mapper, Collector<TT, A, R> downstream) { class Acc { T first, last; A acc = downstream.supplier().get(); void add(T next) { if(last == null) first = next; else downstream.accumulator().accept(acc, mapper.apply(last, next)); last = next; } Acc combine(Acc other) { downstream.accumulator().accept(acc, mapper.apply(last, other.first)); acc = downstream.combiner().apply(acc, other.acc); last = other.last; return this; } } return Collector.of(Acc::new, Acc::add, Acc::combine, acc -> downstream.finisher().apply(acc.acc)); }
  • 63. Задача №14: Разбить входной поток на группы равной длины 63 List<String> input = Arrays.asList ("a", "b", "c", "d", "e", "f", "g", "h"); >> [[a, b, c], [d, e, f], [g, h]]
  • 64. Задача №14: Разбить входной поток на группы равной длины 64 static <T> Stream<List<T>> ofSublists(List<T> list, int n) { int size = list.size(); return IntStream.rangeClosed(0, (size-1) / n).mapToObj(idx -> list.subList(idx * n, Math.min(size, idx * n + n))); } List<String> input = Arrays.asList ("a", "b", "c", "d", "e", "f", "g", "h"); List<List<String>> list = ofSublists(input, 3) .map(ArrayList::new) .collect(Collectors.toList()); >> [[a, b, c], [d, e, f], [g, h]]
  • 65. Задача №15: Разбить входной поток на группы, начинающиеся с данного элемента 65 List<String> input = Arrays.asList("Start", "a", "b", "c", "Start", "d", "Start", "e", "f", "g", "h", "i", "Start"); StreamEx.of(input) .groupRuns((a, b) -> !b.equals("Start")).toList(); >> [[Start, a, b, c], [Start, d], [Start, e, f, g, h, i], [Start]]
  • 66. Задача №15: Разбить входной поток на группы, начинающиеся с данного элемента 66 List<String> input = Arrays.asList("Start", "a", "b", "c", "Start", "d", "Start", "e", "f", "g", "h", "i", "Start"); IntStream.rangeClosed(0, input.size()) .filter(idx -> idx == 0 || idx == input.size() || input.get(idx).equals("Start")) .boxed().collect(pairs(input::subList, Collectors.toList())); >> [[Start, a, b, c], [Start, d], [Start, e, f, g, h, i], [Start]]
  • 67. Библиотеки 67 • jOOλ (by Lukas Eder) • https://github.com/jOOQ/jOOL • Cyclops-react (by John McClean) • https://github.com/aol/cyclops-react • Guava (FluentIterable) • https://github.com/google/guava • javaslang (by Daniel Dietrich) • https://github.com/javaslang/javaslang