Stream Col­lec­tors zijn een krachtige functie in de Java 8 Stream API waarmee u gegevens efficiënt kunt ver­za­me­len en verwerken. Hier leggen we uit hoe ze zijn opgebouwd en hoe u de Java collect()-methode kunt gebruiken.

Hoe kan Java collect() worden gebruikt?

Een Stream Collector kan worden gebruikt om een lijst, set of map te maken op basis van een stream. Een stream is een reeks elementen die achter elkaar worden verwerkt. De Collector-interface biedt een reeks re­duc­tie­be­wer­kin­gen voor gegevens in een stream-pijplijn. Dit zijn terminale be­wer­kin­gen die de re­sul­ta­ten van tus­sen­stap­pen ver­za­me­len en sa­men­voe­gen.

Col­lec­tors kunnen worden gebruikt om objecten uit een stream te filteren of te sorteren. Ag­gre­ga­tie is ook mogelijk, zoals het optellen van getallen, het com­bi­ne­ren van strings of het tellen van elementen. Daarnaast hebben Col­lec­tors functies waarmee de inhoud van een stream kan worden omgezet in een spe­ci­fie­ke structuur. U kunt bij­voor­beeld een lijst omzetten in een map. Groe­pe­rin­gen helpen bij het ca­te­go­ri­se­ren van elementen met bepaalde ei­gen­schap­pen of voor­waar­den. Het be­lang­rijk­ste voordeel van stream­col­lec­tors is dat ze gegevens te­ge­lij­ker­tijd met meerdere threads kunnen verwerken. Hierdoor kunnen be­wer­kin­gen veel sneller en ef­fi­ci­ën­ter worden uit­ge­voerd, vooral bij grote hoe­veel­he­den gegevens.

Wat is de syntaxis voor Java collect()?

De methode ac­cep­teert een Collector die be­schrijft hoe de elementen van de stream moeten worden verzameld en ge­ag­gre­geerd als argument. Een Collector is een interface die ver­schil­len­de methoden biedt om strea­m­ele­men­ten te ag­gre­ge­ren tot een spe­ci­fie­ke vorm, bij­voor­beeld tot een lijst, een set of een map.

Er zijn twee varianten van de Java Stream collect()-methode:

  1. R collect(Supplier<R> le­ve­ran­cier, Bi­Con­su­mer<R, ? super T> ac­cu­mu­la­tor,Bi­Con­su­mer<R, R> combiner)
  2. <R, A> R collect(Collector<? super T, A, R> collector)

De eerste variant heeft drie functies als ar­gu­men­ten:

  • le­ve­ran­cier: maakt een container aan die gebruikt zal worden voor tus­sen­re­sul­ta­ten
  • ac­cu­mu­la­tor: berekent het eind­re­sul­taat
  • combiner: com­bi­neert de re­sul­ta­ten van pa­ral­lel­le stre­am­be­wer­kin­gen

Deze vooraf ge­de­fi­ni­eer­de Col­lec­tors zijn al opgenomen in de stan­daard­bi­bli­o­theek en kunnen eenvoudig worden ge­ïm­por­teerd en gebruikt.

De tweede variant ac­cep­teert een Collector als argument en re­tour­neert een resultaat.

  • R: het type resultaat
  • T: het type elementen in de stream
  • A: het type ac­cu­mu­la­tor dat de tus­sen­lig­gen­de status van de col­lec­tor­be­wer­king opslaat
  • collector: voert de re­duc­tie­be­wer­king uit.

Door deze variant te gebruiken, kunnen ont­wik­ke­laars aan­ge­pas­te Col­lec­tors maken die specifiek zijn afgestemd op hun vereisten en die meer flexi­bi­li­teit en controle bieden over het re­duc­tie­pro­ces.

Wat zijn prak­ti­sche voor­beel­den voor het gebruik van Java collect()?

Hieronder il­lu­stre­ren we ver­schil­len­de functies van de Stream.collect(). Je moet al bekend zijn met de basis Java-ope­ra­to­ren voordat je aan de slag gaat met het col­lec­tiefra­me­work.

Een lijst met strings sa­men­voe­gen

Met Java Collect() kunnen we een lijst met strings sa­men­voe­gen om een nieuwe string te krijgen:

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

De uitvoer is:

abcde
a, b, c, d, e
Java

In de eerste be­re­ke­ning werd slechts één String­Buil­der-instantie gebruikt en was er geen combiner-functie. Daarom is het resultaat abcde.

In de tweede uitvoer heeft de combiner-functie de String­Buil­der-in­stan­ties sa­men­ge­voegd en ze ge­schei­den met een komma.

Verzamel elementen in een lijst met toList()

We kunnen de functie filter() gebruiken om bepaalde elementen van een lijst te se­lec­te­ren en ver­vol­gens toList() gebruiken om ze in een nieuwe lijst op te slaan.

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

In de nieuwe lijst staan alleen oneven getallen:

[1, 3, 5, 7]
Java

Verzamel elementen in een set met toSet()

Op dezelfde manier kunnen we elementen se­lec­te­ren en daaruit een nieuwe set maken. De elementen in een set hoeven niet in een bepaalde volgorde te worden ge­rang­schikt.

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

Dit geeft de volgende uitvoer weer:

[2, 4, 6]
Java

Verzamel elementen in een map met toMap()

Een map kan samen met Java collect() worden gebruikt om aan elke sleutel een waarde toe te wijzen.

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

In de uitvoer zien we dat elk even getal in de invoer een waarde heeft gekregen die identiek is aan het getal zelf:

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

Combineer elementen in een string met joining()

De methode joining() com­bi­neert elementen in een stream in de volgorde waarin ze voorkomen en gebruikt een schei­dings­te­ken om de elementen te scheiden. Het schei­dings­te­ken wordt als argument door­ge­ge­ven aan joining(). Als er geen schei­dings­te­ken is opgegeven, gebruikt joining() de lege te­ken­reeks "".

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

De re­sul­ta­ten zijn:

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