Inleiding tot Java 8-streams

1. Overzicht

In dit artikel zullen we een korte blik werpen op een van de belangrijkste stukjes nieuwe functionaliteit die Java 8 had toegevoegd: Streams.

We zullen uitleggen waar streams over gaan en de creatie en basis stream-bewerkingen laten zien met eenvoudige voorbeelden.

2. Stream API

Een van de belangrijkste nieuwe functies in Java 8 is de introductie van de streamfunctionaliteit - java.util.stream - die klassen bevat voor het verwerken van reeksen elementen.

De centrale API-klasse is de Stroom. In het volgende gedeelte wordt gedemonstreerd hoe streams kunnen worden gemaakt met behulp van de bestaande bronnen van de gegevensprovider.

2.1. Stream creatie

Streams kunnen worden gemaakt op basis van verschillende elementbronnen, bijv. verzameling of array met behulp van stroom() en van() methoden:

String [] arr = nieuwe String [] {"a", "b", "c"}; Stroomstroom = Arrays.stream (arr); stream = Stream.of ("a", "b", "c");

EEN stroom() standaardmethode wordt toegevoegd aan de Verzameling interface en maakt het mogelijk om een Stroom elke verzameling gebruiken als een elementbron:

Stream stream = lijst.stream (); 

2.2. Multi-threading met stromen

Stream API vereenvoudigt ook multithreading door de parallelStream () methode die bewerkingen uitvoert op de elementen van de stream in parallelle modus.

De onderstaande code maakt het mogelijk om de methode uit te voeren werken() parallel voor elk element van de stream:

list.parallelStream (). forEach (element -> doWork (element));

In de volgende sectie zullen we enkele van de basisbewerkingen van Stream API introduceren.

3. Stroombewerkingen

Er zijn veel handige bewerkingen die op een stream kunnen worden uitgevoerd.

Ze zijn onderverdeeld in tussenliggende bewerkingen (terug Stroom) en terminal operaties (retourneer een resultaat van een bepaald type). Tussenliggende bewerkingen maken chaining mogelijk.

Het is ook vermeldenswaard dat bewerkingen op streams de bron niet veranderen.

Hier is een snel voorbeeld:

long count = list.stream (). distinct (). count ();

Dus de onderscheiden () methode vertegenwoordigt een tussenliggende bewerking, die een nieuwe stroom unieke elementen van de vorige stroom creëert. En de tellen () methode is een terminaloperatie, die de grootte van de stream retourneert.

3.1. Itereren

Stream API helpt om voor, voor elk, en terwijl lussen. Het maakt het mogelijk zich te concentreren op de logica van de operatie, maar niet op de iteratie van de opeenvolging van elementen. Bijvoorbeeld:

for (String string: list) {if (string.contains ("a")) {return true; }}

Deze code kan worden gewijzigd met slechts één regel Java 8-code:

boolean isExist = list.stream (). anyMatch (element -> element.contains ("a"));

3.2. Filteren

De filter() methode stelt ons in staat om een ​​stroom elementen te kiezen die aan een predikaat voldoen.

Bekijk bijvoorbeeld de volgende lijst:

ArrayList list = nieuwe ArrayList (); list.add ("Een"); list.add ("OneAndOnly"); list.add ("Derek"); list.add ("Wijzigen"); list.add ("fabriek"); list.add ("justBefore"); list.add ("Italië"); list.add ("Italië"); list.add ("Donderdag"); list.add (""); list.add ("");

De volgende code maakt een Stroom van de Lijst, vindt alle elementen van deze stream die char "d", en maakt een nieuwe stream met alleen de gefilterde elementen:

Stream stream = list.stream (). Filter (element -> element.contains ("d"));

3.3. In kaart brengen

Om elementen van een Stroom door er een speciale functie op toe te passen en deze nieuwe elementen te verzamelen in een Stroom, kunnen we de kaart() methode:

Lijst uris = nieuwe ArrayList (); uris.add ("C: \ Mijn.txt"); Stream stream = uris.stream (). Map (uri -> Paths.get (uri));

Dus de bovenstaande code converteert Stroom naar de Stroom door een specifieke lambda-uitdrukking toe te passen op elk element van de initiaal Stroom.

Als je een stream hebt waarbij elk element zijn eigen reeks elementen bevat en je wilt een stream van deze innerlijke elementen maken, gebruik dan de flatMap () methode:

Lijstdetails = nieuwe ArrayList (); details.add (nieuw Detail ()); Stream stream = details.stream (). FlatMap (detail -> detail.getParts (). Stream ());

In dit voorbeeld hebben we een lijst met elementen van het type Detail. De Detail klasse bevat een veld ONDERDELEN, wat een is Lijst. Met behulp van de flatMap () methode, elk element uit veld ONDERDELEN wordt geëxtraheerd en toegevoegd aan de nieuwe resulterende stream. Daarna de eerste Stroom zal verloren gaan.

3.4. Bij elkaar passen

Stream API biedt een handige set instrumenten om elementen van een reeks te valideren volgens een bepaald predikaat. Om dit te doen, kan een van de volgende methoden worden gebruikt: anyMatch (), allMatch (), noneMatch (). Hun namen spreken voor zich. Dat zijn terminalbewerkingen die een boolean:

boolean isValid = list.stream (). anyMatch (element -> element.contains ("h")); // true boolean isValidOne = list.stream (). allMatch (element -> element.contains ("h")); // false boolean isValidTwo = list.stream (). noneMatch (element -> element.contains ("h")); // false

Voor lege stromen, de allMatch () methode met een bepaald predikaat zal terugkeren waar:

Stream.empty (). AllMatch (Objects :: nonNull); // waar

Dit is een verstandige standaard, omdat we geen enkel element kunnen vinden dat niet aan het predikaat voldoet.

Evenzo is het anyMatch () methode keert altijd terug false voor lege streams:

Stream.empty (). AnyMatch (Objects :: nonNull); // false

Nogmaals, dit is redelijk, omdat we geen element kunnen vinden dat aan deze voorwaarde voldoet.

3.5. Vermindering

Stream API maakt het mogelijk om een ​​reeks elementen tot een bepaalde waarde te reduceren volgens een gespecificeerde functie met behulp van de verminderen() methode van het type Stroom. Deze methode heeft twee parameters nodig: eerste - startwaarde, tweede - een accumulatorfunctie.

Stel je voor dat je een Lijst en je wilt een som hebben van al deze elementen en een aantal initiaal Geheel getal (in dit voorbeeld 23). U kunt dus de volgende code uitvoeren en het resultaat is 26 (23 + 1 + 1 + 1).

Lijst gehele getallen = Arrays.asList (1, 1, 1); Geheel getal gereduceerd = gehele getallen. Stroom (). Reduceren (23, (a, b) -> a + b);

3.6. Verzamelen

De verlaging kan ook worden geleverd door de verzamelen() methode van het type Stroom. Deze handeling is erg handig bij het converteren van een stream naar een Verzameling of een Kaart en het vertegenwoordigen van een stroom in de vorm van een enkele string. Er is een hulpprogramma-klasse Verzamelaars die een oplossing bieden voor bijna alle typische verzamelhandelingen. Voor sommige, niet triviale taken, een gewoonte Verzamelaar kan worden gemaakt.

Lijst resultList = list.stream (). Map (element -> element.toUpperCase ()). Collect (Collectors.toList ());

Deze code gebruikt de terminal verzamelen() operatie om een ​​te verminderen Stroom naar de Lijst.

4. Conclusies

In dit artikel hebben we kort gesproken over Java-streams - absoluut een van de meest interessante Java 8-functies.

Er zijn veel meer geavanceerde voorbeelden van het gebruik van Streams; het doel van dit artikel was alleen om een ​​snelle en praktische introductie te geven van wat u kunt gaan doen met de functionaliteit en als een startpunt voor onderzoek en verder leren.

De broncode die bij het artikel hoort, is beschikbaar op GitHub.