1. Kolekcja elementów
I wreszcie doszliśmy do najciekawszej metody w klasie Stream- metody collect(). Służy do przechodzenia ze strumieni do znanych kolekcji — List<T>, Set<T>, Map<T, R>i innych.
Musisz przekazać specjalny obiekt do metody collect()- collector. Ten obiekt odczytuje wszystkie dane ze strumienia, konwertuje je na określoną kolekcję i zwraca. A potem sama metoda collect zwraca tę samą kolekcję.
Wszystko to odbywa się dość sprytnie: obiekt collectorma typ Collector<T, A, R>- ma już trzy parametry typu. Ostatnim typem Rjest zwykle typ taki jak List<T>. Dlatego kompilator może zastąpić ten typ poprawnym typem wyniku samej metody collect().
Mam nadzieję, że nie jesteś zbyt zdezorientowany. W każdym razie nie musisz samodzielnie tworzyć obiektów Collector. Wystarczy skorzystać z gotowych obiektów, które zwracają statyczne metody Collectors.
Klasa kolekcjonerska
Klasa Collectorsposiada kilka metod statycznych, które zwracają gotowe obiekty kolekcjonerskie na każdą okazję. Jest ich kilkadziesiąt, ale rozważymy te najbardziej podstawowe:
|
Obiekt, który konwertuje strumień na listę −List<T> |
|
Obiekt, który konwertuje strumień na zbiór −Set<T> |
|
Obiekt, który konwertuje strumień na mapę −Map<K, V> |
|
Łączy elementy strumienia w jedną linię |
|
Konwertuje elementy strumienia naMap<K, V> |
|
Grupy elementów, zwrotyMap <K, V> |
2. Konwertuj strumień na listę
Tak wygląda typowa praca ze strumieniem i zamiana wyniku pracy na listę
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Cześć", "Jak", "дела?");
List<String> result = list.stream()
.filter( s -> Character.isUpperCase(s.charAt(0)) )
.collect( Collectors.toList() );
Otrzymaliśmy strumień z kolekcji, a następnie otrzymaliśmy z niego nowy strumień, odfiltrowując tylko wiersze, których pierwszy znak jest pisany wielką literą. Następnie wszystkie dane z ostatniego strumienia zostały zebrane w kolekcję i zwrócone.
3. Przekształcenie strumienia w zestaw
Tak wygląda typowa praca ze strumieniem i przekształcenie wyniku pracy w zestaw
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "Cześć", "Jak", "дела?");
Set<String> result = list.stream()
.filter( s -> Character.isUpperCase(s.charAt(0)) )
.collect( Collectors.toSet() );
Wszystko jest bardzo podobne do kodu konwersji strumienia na List, tylko używany jest inny obiekt kolektora, który zwraca metodętoSet();
4. Konwertuj strumień na mapę
Jednak konwersja strumienia na mapę jest nieco trudniejsza. W końcu każdy obiekt Map składa się z dwóch elementów – klucza i wartości. Musimy dowiedzieć się, jak zdefiniujemy klucz dla elementu strumienia i jak zdefiniujemy wartość.
Przykład.
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "a=2", "b=3", "c=4", "d==3");
Map<String, String> result = list.stream()
.map( e -> e.split("=") )
.filter( e -> e.length == 2 )
.collect( Collectors.toMap(e -> e[0], e -> e[1]) );
Przyjrzyjmy się, co się tutaj dzieje.
W pierwszym wierszu map(...)konwertujemy każdy ciąg na tablicę ciągów. Korzystając z metody split, dzielimy każdy ciąg na dwie równe części.
W drugiej linii - metodzie filter()- przepuszczamy przez filtr tylko te elementy tablicy, które zawierają dokładnie dwa elementy. Element d == 3został podzielony na tablicę trzech elementów i filtr zakończy się niepowodzeniem.
I wreszcie, w ostatnim wierszu, zamieniamy strumień na Map<String, String>. Do metody toMap()przekazywane są dwie funkcje . Dla każdego elementu strumienia pierwsza funkcja powinna zwrócić klucz , a druga wartość .
Pierwszy element tablicy („a”, „b”, „c”) będziemy mieć jako klucz, a drugi element tablicy jako wartości: „2”, „3”, „4”.
5. Konwertuj strumień na łańcuch
Innym ciekawym obiektem kolekcjonerskim jest Collectors.joining(). Konwertuje wszystkie elementy strumienia na typ Stringi łączy je w jeden ciąg. Przykład
ArrayList<String> list = new ArrayList<String>();
Collections.addAll(list, "a=2", "b=3", "c=4", "d==3");
String result = list.stream().collect( Collectors.joining(", ") );
GO TO FULL VERSION