Sprievodca zoskupovaním Java 8 pomocou nástroja Collector

1. Úvod

V tomto návode uvidíme ako zoskupenieBy zberateľské práce na rôznych príkladoch.

Aby sme pochopili materiál popísaný v tomto výučbe, budeme potrebovať základné znalosti o funkciách Java 8. Môžeme sa pozrieť na úvod do streamov Java 8 a sprievodcu zberateľmi Java 8 pre tieto základné informácie.

2. zoskupenieBy Zberatelia

Java 8 Prúd API nám umožňuje spracovávať zbierky údajov deklaratívnym spôsobom.

Statická továrenská metóda Collectors.groupingBy () a Collectors.groupingByConcurrent () poskytnúť nám funkčnosť podobnú „ZOSKUPIŤ PODĽA klauzula v jazyku SQL. Používame ich na zoskupovanie objektov podľa niektorých vlastností a ukladanie výsledkov do a Mapa inštancia.

Preťažené metódy zoskupenieBy sú:

  • Najskôr s klasifikačnou funkciou ako parametrom metódy:

statický zberač<>> groupingBy (klasifikátor funkcií)
  • Po druhé, s klasifikačnou funkciou a druhým kolektorom ako parametrami metódy:

statický zberač groupingBy (klasifikátor funkcií, zberateľ po prúde)
  • Nakoniec s klasifikačnou funkciou metóda dodávateľa (ktorá poskytuje Mapa implementácia, ktorá obsahuje konečný výsledok) a druhý kolektor ako parametre metódy:

statický  Collector groupingBy (Klasifikátor funkcií, Supplier mapFactory, Collector downstream)

2.1. Príklad nastavenia kódu

Na preukázanie použitia groupingBy (), definujme a Príspevok v blogu triedy (použijeme prúd Príspevok v blogu predmety):

trieda BlogPost {Názov reťazca; Autor reťazca; Typ BlogPostType; int má rád; } 

Ďalej BlogPostType:

enum BlogPostType {NOVINY, RECENZIA, PRÍRUČKA} 

Potom Zoznam z Príspevok v blogu objekty:

Zoznam príspevkov = Arrays.asList (...);

Definujme tiež a Násobný triedy, ktoré sa použijú na zoskupenie príspevkov podľa ich kombinácie typu a autor atribúty:

trieda Tuple {BlogPostType type; Autor reťazca; } 

2.2. Jednoduché zoskupenie do jedného stĺpca

Začnime tým najjednoduchším zoskupenieBy metóda, ktorá berie ako svoj parameter iba klasifikačnú funkciu. Na každý prvok streamu sa použije klasifikačná funkcia. Hodnotu vrátenú funkciou použijeme ako kľúč k mape, ktorú dostaneme z zoskupenieBy zberateľ.

Ak chcete zoskupiť blogové príspevky v zozname blogových príspevkov podľa nich typu:

Mapa postsPerType = posts.stream () .collect (groupingBy (BlogPost :: getType)); 

2.3. zoskupenieBy s Komplexom Mapa Typ kľúča

Funkcia klasifikácie sa neobmedzuje iba na vrátenie iba skalárnej alebo reťazcovej hodnoty. Kľúčom výslednej mapy môže byť akýkoľvek objekt, pokiaľ sa uistíme, že implementujeme potrebné rovná sa a hashcode metódy.

Ak chcete zoskupiť blogové príspevky v zozname podľa typu a autor kombinované v a Násobný inštancia:

Mapa postsPerTypeAndAuthor = posts.stream () .collect (groupingBy (post -> new Tuple (post.getType (), post.getAuthor ()))); 

2.4. Úpravy vrátených Mapa Typ hodnoty

Druhé preťaženie zoskupenieBy vezme ďalší druhý kolektor (následný kolektor), ktorý sa použije na výsledky prvého kolektora.

Keď zadáme klasifikačnú funkciu, ale nie následný kolektor, listovať() v zákulisí sa používa kolektor.

Použime nastaviť() zberateľ ako následný zberateľ a získajte a Nastaviť blogových príspevkov (namiesto a Zoznam):

Mapa postsPerType = posts.stream () .collect (groupingBy (BlogPost :: getType, toSet ())); 

2.5. Zoskupenie podľa viacerých polí

Inou aplikáciou následného kolektora je sekundárne zoskupenieBy k výsledkom prvej skupiny do.

Do skupiny Zoznam z Príspevok v blogus najskôr o autor a potom typu:

Mapa map = posts.stream () .collect (groupingBy (BlogPost :: getAuthor, groupingBy (BlogPost :: getType)));

2.6. Získanie priemeru zo zoskupených výsledkov

Použitím následného kolektora môžeme vo výsledkoch klasifikačnej funkcie použiť agregačné funkcie.

Napríklad na zistenie priemerného počtu má rád pre každý blogový príspevok typu:

Mapa averageLikesPerType = posts.stream () .collect (groupingBy (BlogPost :: getType, averagingInt (BlogPost :: getLikes))); 

2.7. Získanie súčtu zo zoskupených výsledkov

Ak chcete vypočítať celkový súčet má rád pre každý typu:

Mapa má rádPerType = posts.stream () .collect (groupingBy (BlogPost :: getType, summingInt (BlogPost :: getLikes))); 

2.8. Získanie maxima alebo minima zo zoskupených výsledkov

Ďalšou agregáciou, ktorú môžeme vykonať, je získanie blogového príspevku s maximálnym počtom označení Páči sa mi:

Mapa maxLikesPerPostType = posts.stream () .collect (groupingBy (BlogPost :: getType, maxBy (comparingInt (BlogPost :: getLikes))))); 

Podobne môžeme použiť minBy následný zberateľ a získať tak blogový príspevok s minimálnym počtom má rád.

Všimnite si, že maxBy a minBy zberatelia berú do úvahy možnosť, že zbierka, na ktorú sa vzťahujú, môže byť prázdna. Preto je typ hodnoty na mape Voliteľné.

2.9. Získanie súhrnu za atribút zoskupených výsledkov

The Zberatelia API ponúka súhrnný kolektor, ktorý môžeme použiť v prípadoch, keď potrebujeme súčasne vypočítať počet, súčet, minimum, maximum a priemer číselného atribútu.

Vypočítajme súhrn atribútov páči sa mi blogových príspevkov pre každý iný typ:

Mapa likeStatisticsPerType = posts.stream () .collect (groupingBy (BlogPost :: getType, summarizingInt (BlogPost :: getLikes))); 

The IntSummaryStatistics objekt pre každý typ obsahuje počet, súčet, priemer, min a max hodnoty pre má rád atribút. Pre dvojité a dlhé hodnoty existujú ďalšie objekty súhrnu.

2.10. Mapovanie zoskupených výsledkov na iný typ

Zložitejšie agregácie môžeme dosiahnuť aplikáciou a mapovanie následný kolektor k výsledkom klasifikačnej funkcie.

Poďme do zreťazenia tituls príspevkov pre každý blogový príspevok typu:

Map postsPerType = posts.stream () .collect (groupingBy (BlogPost :: getType, mapping (BlogPost :: getTitle, joining (",", "Názvy príspevkov: [", "]")))); 

To, čo sme tu vykonali, je mapovanie každého z nich Príspevok v blogu inštancie k jeho titul a potom znížte prúd názvov príspevkov na zreťazené String. V tomto príklade je typ Mapa hodnota sa tiež líši od predvolenej Zoznam typu.

2.11. Úprava návratnosti Mapa Typ

Pri použití zoskupenieBy zberateľ, nemôžeme predpokladať o type vráteného Mapa. Ak chceme byť konkrétni, o aký typ Mapa chceme sa dostať zo skupiny do, potom môžeme použiť tretiu variáciu zoskupenieBy metóda, ktorá nám umožňuje zmeniť typ súboru Mapa prejdením a Mapa dodávateľská funkcia.

Poďme získať EnumMap absolvovaním an EnumMap dodávateľská funkcia do zoskupenieBy metóda:

EnumMap postsPerType = posts.stream () .collect (groupingBy (BlogPost :: getType, () -> nový EnumMap (BlogPostType.class), toList ())); 

3. Súbežné zoskupenieBy Zberateľ

Podobný zoskupenieBy je groupingByConcurrent collector, ktorý využíva viacjadrové architektúry. Tento kolektor má tri preťažené metódy, ktoré berú úplne rovnaké argumenty ako príslušné preťažené metódy zoskupenieBy zberateľ. Návratový typ groupingByConcurrent zberateľ však musí byť inštanciou ConcurrentHashMap trieda alebo jej podtrieda.

Ak chcete vykonať operáciu zoskupenia súčasne, prúd musí byť paralelný:

ConcurrentMap postsPerType = posts.parallelStream () .collect (groupingByConcurrent (BlogPost :: getType)); 

Ak sa rozhodneme prejsť a Mapa dodávateľská funkcia do groupingByConcurrent kolektor, potom sa musíme ubezpečiť, že funkcia vráti buď a ConcurrentHashMap alebo jeho podtrieda.

4. Doplnky Java 9

Java 9 predstavila dva nové zberače, s ktorými sa dobre pracuje zoskupenieBy; viac informácií o nich nájdete tu.

5. Záver

V tomto článku sme preskúmali možnosti použitia zoskupenieBy zberač ponúkaný Java 8 Zberatelia API.

Dozvedeli sme sa ako zoskupenieBy možno použiť na klasifikáciu toku prvkov na základe jedného z ich atribútov a na to, ako je možné výsledky tejto klasifikácie ďalej zhromažďovať, mutovať a redukovať na konečné obaly.

Kompletnú implementáciu príkladov v tomto článku nájdete v projekte GitHub.


$config[zx-auto] not found$config[zx-overlay] not found