Inleiding tot StreamEx

1. Overzicht

Een van de meest opwindende functies van Java 8 is de Stroom API - wat, simpel gezegd, een krachtig hulpmiddel is voor het verwerken van reeksen elementen.

StreamEx is een bibliotheek die naast de prestatieverbeteringen extra functionaliteit biedt voor de standaard Stream API.

Hier zijn een paar kernfuncties:

  • Kortere en gemakkelijkere manieren om de dagelijkse taken uit te voeren
  • 100% compatibiliteit met originele JDK Streams
  • Vriendelijkheid voor parallelle verwerking: elke nieuwe functie maakt zoveel mogelijk gebruik van parallelle streams
  • Prestaties en minimale overhead. Als StreamEx maakt het mogelijk om de taak op te lossen met minder code in vergelijking met standaard Stroom, het zou niet significant langzamer moeten zijn dan de gebruikelijke manier (en soms is het zelfs sneller)

In deze zelfstudie presenteren we enkele functies van StreamEx API.

2. Het voorbeeld opstellen

Gebruiken StreamEx, moeten we de volgende afhankelijkheid toevoegen aan het pom.xml:

 one.util streamex 0.6.5 

De nieuwste versie van de bibliotheek is te vinden op Maven Central.

Via deze tutorial gaan we een simple gebruiken Gebruiker klasse:

openbare klasse Gebruiker {int id; String naam; Rol rol = nieuwe rol (); // standaard getters, setters en constructors}

En een simpele Rol klasse:

openbare klas Rol {}

3. Snelkoppelingsmethoden voor verzamelaars

Een van de meest populaire terminaloperaties van Streams is de verzamelen operatie; dit maakt herverpakking mogelijk Stroom elementen toe aan een collectie naar keuze.

Het probleem is dat code onnodig uitgebreid kan worden voor eenvoudige scenario's:

users.stream () .map (Gebruiker :: getName) .collect (Collectors.toList ());

3.1. Verzamelen in een verzameling

Nu, met StreamEx, hoeven we geen Verzamelaar om te specificeren dat we een Lijst, Set, Map, InmutableList, enz.:

Lijst userNames = StreamEx.of (gebruikers) .map (Gebruiker :: getName) .toList ();

De verzamelen -bewerking is nog steeds beschikbaar in de API als we iets ingewikkelder willen uitvoeren dan elementen uit een Stroom en ze in een verzameling stoppen.

3.2. Geavanceerde verzamelaars

Een andere afkorting is groupingBy:

Kaart role2users = StreamEx.of (gebruikers) .groupingBy (Gebruiker :: getRole);

Dit zal een Kaart met het sleuteltype dat is opgegeven in de methodeverwijzing, waardoor iets wordt geproduceerd dat lijkt op de groep door bewerking in SQL.

Gebruik gewoon Stroom API, we zouden moeten schrijven:

Kaart role2users = users.stream () .collect (Collectors.groupingBy (Gebruiker :: getRole));

Een soortgelijk steno-formulier is te vinden voor de Collectors.joining ():

StreamEx.of (1, 2, 3) .joining (";"); // "1; 2; 3"

Die alle elementen in de Stroom a produceert een Draad ze allemaal aaneenschakelen.

4. Elementen toevoegen, verwijderen en selecteren

In sommige scenario's we hebben een lijst met objecten van verschillende typen, en we moeten ze filteren op type:

Lijst usersAndRoles = Arrays.asList (nieuwe gebruiker (), nieuwe rol ()); Lijst met rollen = StreamEx.of (usersAndRoles) .selecteer (Role.class) .toList ();

We kunnen elementen toevoegen aan het begin of einde van onze Stroom, met deze handige bewerkingen:

Lijst appendedUsers = StreamEx.of (gebruikers) .map (Gebruiker :: getName) .prepend ("(geen)") .append ("LAST") .toList ();

We kunnen ongewenste null-elementen verwijderen met nonNull () en gebruik de Stroom als een Herhaalbaar:

voor (String line: StreamEx.of (gebruikers) .map (User :: getName) .nonNull ()) {System.out.println (regel); }

5. Ondersteuning voor wiskundige bewerkingen en primitieve typen

StreamEx voegt ondersteuning toe voor primitieve typen, zoals we kunnen zien in dit zelfverklarende voorbeeld:

korte [] src = {1,2,3}; char [] output = IntStreamEx.of (src) .map (x -> x * 5) .toCharArray ();

Laten we nu een reeks nemen van dubbele elementen op een ongeordende manier. We willen een array maken die bestaat uit het verschil tussen elk paar.

We kunnen de pairMap methode om deze bewerking uit te voeren:

openbare dubbele [] getDiffBetweenPairs (dubbele ... getallen) {retour DoubleStreamEx.of (getallen) .pairMap ((a, b) -> b - a) .toArray (); }

6. Kaartbewerkingen

6.1. Filteren op sleutels

Een andere handige functie is de mogelijkheid om een Stroom van een Kaart en filter de elementen door de waarden te gebruiken waarnaar ze verwijzen.

In dit geval nemen we alle niet-null-waarden:

Map nameToRole = nieuwe HashMap (); nameToRole.put ("eerste", nieuwe rol ()); nameToRole.put ("second", null); Stel nonNullRoles = StreamEx.ofKeys (nameToRole, Objects :: nonNull) .toSet ();

6.2. Werken met sleutelwaardeparen

We kunnen ook werken met sleutel-waardeparen door een EntryStream voorbeeld:

openbare kaart transformMap (Map role2users) {Map users2roles = EntryStream.of (role2users) .flatMapValues ​​(Lijst :: stream) .invert () .grouping (); terug users2roles; }

De speciale operatie EntryStream.of duurt een Kaart en transformeert het in een Stroom van sleutelwaarde-objecten. Dan gebruiken we flatMapValues bewerking om onze lijst met rollen om te zetten in een Stroom van enkele waarden.

Vervolgens kunnen we omkeren het sleutel / waarde-paar, waardoor de Gebruiker klasse de sleutel en de Rol klasse de waarde.

En tot slot kunnen we de groepering operatie om onze kaart te transformeren naar de inversie van de ontvangen kaart, allemaal met slechts vier bewerkingen.

6.3. Toewijzing van sleutelwaarden

We kunnen sleutels en waarden ook onafhankelijk toewijzen:

Map mapToString = EntryStream.of (users2roles) .mapKeys (String :: valueOf) .mapValues ​​(String :: valueOf) .toMap ();

Hiermee kunnen we onze sleutels of waarden snel naar een ander vereist type transformeren.

7. Bestandsbewerkingen

Gebruik makend van StreamExkunnen we bestanden efficiënt lezen, d.w.z. zonder volledige bestanden tegelijk te laden. Het is handig bij het verwerken van grote bestanden:

StreamEx.ofLines (lezer) .remove (String :: isEmpty) .forEach (System.out :: println);

Merk op dat we hebben gebruikt verwijderen() methode om lege regels weg te filteren.

Punt om op te merken is dat StreamEx zal het bestand niet automatisch sluiten. Daarom moeten we niet vergeten om handmatig een sluitbewerking uit te voeren bij zowel het lezen als schrijven van bestanden om onnodige geheugenoverhead te vermijden.

8. Conclusie

In deze tutorial hebben we geleerd over StreamEx, en het zijn verschillende hulpprogramma's. Er is nog veel meer om door te nemen - en ze hebben hier een handig spiekbriefje.

Zoals altijd is de volledige broncode beschikbaar op GitHub.