Stream Col­lec­tors on Java 8 Stream API: n tehokas omi­nai­suus, jonka avulla voit kerätä ja käsitellä dataa te­hok­kaas­ti. Tässä selitämme niiden rakenteen ja miten Java collect() -metodia voidaan käyttää.

Miten Java collect()-funktiota voidaan käyttää?

Stream Collector -työkalua voidaan käyttää luomaan luettelo, joukko tai kartta strea­mis­ta. Stream on peräkkäin kä­si­tel­tä­vien ele­ment­tien sarja. Collector-rajapinta tarjoaa joukon re­duk­tiopro­ses­se­ja stream-putken dataa varten. Nämä ovat pää­te­toi­min­to­ja, jotka keräävät ja yh­dis­tä­vät vä­li­vai­hei­den tulokset.

Kerääjiä voidaan käyttää suo­dat­ta­maan tai la­jit­te­le­maan objektit virrasta. Myös aggre­goin­ti on mah­dol­lis­ta, kuten nu­me­roi­den sum­maa­mi­nen, merk­ki­jo­no­jen yh­dis­tä­mi­nen tai ele­ment­tien las­ke­mi­nen. Lisäksi ke­rää­jil­lä on toi­min­to­ja, joilla virran sisältö voidaan muuntaa tiettyyn ra­ken­tee­seen. Voit esi­mer­kik­si muuntaa luettelon kartaksi. Ryh­mit­te­lyt auttavat luo­kit­te­le­maan elementit tiettyjen omi­nai­suuk­sien tai ehtojen pe­rus­teel­la. Tärkeintä on, että Stream Col­lec­tors -ke­rää­jil­lä on se etu, että ne voivat käsitellä dataa sa­ma­nai­kai­ses­ti useilla säikeillä. Tämä mah­dol­lis­taa toi­min­to­jen suo­rit­ta­mi­sen paljon nopeammin ja te­hok­kaam­min, eri­tyi­ses­ti suurten da­ta­mää­rien kanssa.

Mikä on Java collect()-komennon syntaksi?

Menetelmä hyväksyy ar­gu­ment­ti­na Col­lec­to­rin, joka kuvaa, miten streamin elementit tulisi kerätä ja aggre­goi­da. Collector on rajapinta, joka tarjoaa erilaisia me­ne­tel­miä stream-ele­ment­tien aggre­goi­mi­sek­si tiettyyn muotoon, esi­mer­kik­si luet­te­lok­si, joukkoksi tai kartaksi.

Java Stream -metodissa collect() on kaksi va­riant­tia:

  1. R collect(Supplier<R> toi­mit­ta­ja, BiCon­su­mer<R, ? super T> ak­ku­mu­laat­to­ri, BiCon­su­mer<R, R> yh­dis­te­li­jä)
  2. <R, A> R collect(Collector<? super T, A, R> collector)

En­sim­mäi­ses­sä va­rian­tis­sa on kolme funktiota ar­gu­ment­tei­na:

  • toi­mit­ta­ja: luo vä­li­tu­lok­sia varten käy­tet­tä­vän säi­ly­tys­pai­kan
  • accu­mu­la­tor: laskee lo­pul­li­sen tuloksen
  • yh­dis­tel­mä­lai­te: yhdistää rin­nak­kais­ten vir­tao­pe­raa­tioi­den tulokset

Nämä ennalta mää­ri­tel­lyt kerääjät si­säl­ty­vät jo va­kio­kir­jas­toon, ja ne on helppo tuoda ja käyttää.

Toinen variantti hyväksyy Col­lec­to­rin ar­gu­ment­ti­na ja palauttaa tuloksen.

  • R: tuloksen tyyppi
  • T: virran ele­ment­tien tyyppi
  • A: kerääjän toiminnan vä­li­vai­heen tilan tal­len­ta­van ak­ku­mu­laat­to­rin tyyppi
  • kerääjä: suorittaa pel­kis­ty­so­pe­raa­tion.

Tätä vaih­toeh­toa käyt­tä­mäl­lä ke­hit­tä­jät voivat luoda rää­tä­löi­ty­jä kerääjiä, jotka on eri­tyi­ses­ti sovitettu heidän vaa­ti­muk­siin­sa ja jotka tarjoavat suuremman jous­ta­vuu­den ja hallinnan vä­hen­tä­mispro­ses­sis­sa.

Mitä ovat käytännön esi­merk­ke­jä Java collect()-funktion käytöstä?

Alla kuvataan Stream.collect() -me­ne­tel­män erilaisia toi­min­to­ja. Sinun tulisi olla jo pe­reh­ty­nyt Java-ope­raat­to­rei­den pe­rus­tei­siin ennen kuin siirryt ko­koel­ma­ke­hyk­seen.

Yhdistä merk­ki­jo­no­jen luettelo

Java Collect() -toi­min­nol­la voimme yhdistää merk­ki­jo­no­jen luettelon saa­dak­sem­me uuden merk­ki­jo­non:

List<String> letters = List.of("a", "b", "c", "d", "e");
// without combiner function
StringBuilder result = letters.stream().collect(StringBuilder::new, (x, y) -> x.append(y),
    (a, b) -> a.append(",").append(b));
System.out.println(result.toString());
// with combiner function
StringBuilder result1 = letters.parallelStream().collect(StringBuilder::new, (x, y) -> x.append(y),
    (a, b) -> a.append(",").append(b));
System.out.println(result1.toString());
Java

Tulostus on:

abcde
a, b, c, d, e
Java

En­sim­mäi­ses­sä las­kel­mas­sa käy­tet­tiin vain yhtä String­Buil­der-il­men­ty­mää eikä yh­dis­tä­mis­toi­min­toa. Siksi tulos on abcde.

Toisessa tu­lok­ses­sa yh­dis­tä­mis­toi­min­to yhdisti String­Buil­der-il­men­ty­mät ja erotti ne toi­sis­taan pilkulla.

Kerää elementit luet­te­loon toList()-funk­tiol­la

Voimme käyttää filter() va­li­tak­sem­me tietyt elementit listasta ja sitten käyttää toList() tal­len­taak­sem­me ne uuteen listaan.

List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
List<Integer> oddNumbers = numbers.stream().filter(x -> x % 2 != 0).collect(Collectors.toList());
System.out.println(oddNumbers);
Java

Uudessa luet­te­los­sa on vain pa­rit­to­mia lukuja:

[1, 3, 5, 7]
Java

Kerää elementit joukkoon toSet()-funk­tiol­la

Vas­taa­vas­ti voimme valita ele­ment­te­jä ja luoda niistä uuden joukon. Joukon ele­ment­tien ei tarvitse olla jär­jes­tet­tyi­nä tiettyyn jär­jes­tyk­seen.

List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
Set<Integer> evenNumbers = numbers.parallelStream().filter(x -> x % 2 == 0).collect(Collectors.toSet());
System.out.println(evenNumbers);
Java

Tämä näyttää tuloksen:

[2, 4, 6]
Java

Kerää elementit karttaan toMap()-funk­tiol­la

Karttaa voidaan käyttää yhdessä Java collect() -komennon kanssa arvon mää­rit­tä­mi­sek­si kullekin avaimelle.

List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6, 7);
Map<Integer, String> mapEvenNumbers = numbers.parallelStream().filter(x -> x % 2 == 0)
    .collect(Collectors.toMap(Function.identity(), x -> String.valueOf(x)));
System.out.println(mapEvenNumbers);
Java

Tu­lok­ses­sa voimme nähdä, että jo­kai­sel­le syötteen pa­ril­li­sel­le luvulle on annettu sama arvo kuin sille:

{2=2, 4=4, 6=6}
Java

Yhdistä merk­ki­jo­non elementit joining()-funk­tiol­la

joining() yhdistää elementit virrassa niiden esiin­ty­mis­jär­jes­tyk­ses­sä ja käyttää erottinta ele­ment­tien erot­ta­mi­seen. Erottin vä­li­te­tään ar­gu­ment­ti­na joining()lle. Jos erottinta ei ole mää­ri­tet­ty, joining() käyttää tyhjää merk­ki­jo­noa "".

jshell> String result1 = Stream.of("a", "b", "c").collect(Collectors.joining());
jshell> String result2 = Stream.of("a", "b", "c").collect(Collectors.joining(",", "{", "}"));
Java

Tulokset ovat:

result1 ==> "abc"
result2 ==> "{a,b,c}"
Java

4badd840839b54cea0232685028c6727

Siirry pää­va­lik­koon