Arbejde med kort ved hjælp af streams

1. Introduktion

I denne vejledning diskuterer vi nogle eksempler på, hvordan du bruger Java Strømsat arbejde med Korts. Det er værd at bemærke, at nogle af disse øvelser kunne løses ved hjælp af en tovejs Kort datastruktur, men vi er interesseret her i en funktionel tilgang.

Først forklarer vi den grundlæggende idé, vi vil bruge til at arbejde med Kort og Strøms. Derefter præsenterer vi et par forskellige problemer relateret til Kort og deres konkrete løsninger ved hjælp af Strøms.

2. Grundlæggende idé

Det vigtigste at bemærke er, at Strøms er sekvenser af elementer, som let kan opnås fra a Kollektion.

Kort har en anden struktur med en kortlægning fra nøgler til værdier uden sekvens. Dette betyder ikke, at vi ikke kan konvertere en Kort struktur i forskellige sekvenser, som derefter giver os mulighed for at arbejde på en naturlig måde med Stream API.

Lad os se måder at opnå forskellige på Kollektions fra en Kort, som vi derefter kan dreje ind i en Strøm:

Kort someMap = ny HashMap ();

Vi kan få et sæt nøgleværdipar:

Sæt poster = someMap.entrySet ();

Vi kan også få nøglesættet tilknyttet Kort:

Indstil keySet = someMap.keySet ();

Eller vi kunne arbejde direkte med værdisættet:

Samlingsværdier = someMap.values ​​();

Disse giver os hver et indgangspunkt til at behandle disse samlinger ved at få streams fra dem:

Strøm entriesStream = entries.stream (); Strømværdier Strøm = værdier.strøm (); Stream nøglerStream = keySet.stream ();

3. At få en Kort'S taster bruger Strøms

3.1. Indtastningsdata

Lad os antage, at vi har en Kort:

Kortbøger = nyt HashMap (); books.put ("978-0201633610", "Designmønstre: elementer i genanvendelig objektorienteret software"); books.put ("978-1617291999", "Java 8 in Action: Lambdas, Streams og funktionel stil programmering"); books.put ("978-0134685991", "Effektiv Java");

Vi er interesserede i at finde bogens ISBN med titlen “Effektiv Java”.

3.2. Henter en kamp

Da bogtitlen ikke kunne eksistere i vores Kort, vi ønsker at kunne angive, at der ikke er noget tilknyttet ISBN til det. Vi kan bruge en Valgfri at udtrykke det:

Lad os antage for dette eksempel, at vi er interesserede i enhver nøgle til en bog, der matcher den titel:

Valgfri optionalIsbn = books.entrySet (). Stream () .filter (e -> "Effektiv Java" .equals (e.getValue ())). Kort (Map.Entry :: getKey) .findFirst (); assertEquals ("978-0134685991", optionalIsbn.get ());

Lad os analysere koden. Først, vi får entrySet fra Kort, som vi så tidligere.

Vi vil kun betragte posterne med “Effektiv Java” som titlen, så den første mellemhandling vil være et filter.

Vi er ikke interesserede i det hele Kort post, men i nøglen til hver post. Så den næste kædede mellemoperation gør netop det: det er en kort operation, der genererer en ny stream som output, der kun indeholder nøglerne til de poster, der matchede den titel, vi ledte efter.

Da vi kun ønsker et resultat, kan vi anvende findFirst () terminaloperation, som giver den oprindelige værdi i Strøm som en Valgfri objekt.

Lad os se et tilfælde, hvor en titel ikke findes:

Valgfri optionalIsbn = books.entrySet (). Stream () .filter (e -> "Ikke eksisterende titel" .equals (e.getValue ())). Kort (Map.Entry :: getKey) .findFirst (); assertEquals (false, optionalIsbn.isPresent ());

3.3. Henter flere resultater

Lad os ændre problemet nu for at se, hvordan vi kunne håndtere at returnere flere resultater i stedet for et.

For at få flere resultater returneret, lad os tilføje følgende bog til vores Kort:

books.put ("978-0321356680", "Effektiv Java: Anden udgave"); 

Så nu, hvis vi ser efter alle bøger, der starter med “Effektiv Java”, får vi mere end et resultat tilbage:

Liste isbnCodes = books.entrySet (). Stream () .filter (e -> e.getValue (). StartsWith ("Effective Java")) .map (Map.Entry :: getKey) .collect (Collectors.toList () ); assertTrue (isbnCodes.contains ("978-0321356680")); assertTrue (isbnCodes.contains ("978-0134685991"));

Hvad vi har gjort i dette tilfælde er at erstatte filtertilstanden for at kontrollere, om værdien i Kort starter med “Effektiv Java” i stedet for at sammenligne for Snor lighed.

Denne gang, vi indsamle resultaterne - i stedet for at vælge den første - sætte tændstikkerne i en Liste.

4. At få en Kort‘S Værdier ved hjælp af Strøms

Lad os nu fokusere på et andet problem med kort: I stedet for at opnå ISBN'er baseret på titler, vi prøver at få titler baseret på ISBN'er.

Lad os bruge originalen Kort. Vi vil finde titler, hvor deres ISBN starter med "978-0".

Liste titler = books.entrySet (). Stream () .filter (e -> e.getKey (). StartsWith ("978-0")) .map (Map.Entry :: getValue) .collect (Collectors.toList ( )); assertEquals (2, titler. størrelse ()); assertTrue (titler.contains ("Designmønstre: elementer i genanvendelig objektorienteret software")); assertTrue (titler. indeholder ("Effektiv Java"));

Denne løsning svarer til løsningerne på vores tidligere sæt problemer - vi streamer indgangssættet og filtrerer derefter, kortlægger og indsamler.

Og som før, hvis vi kun ønskede at vende tilbage den første kamp, ​​kunne vi efter den kort metode kalder findFirst () metode i stedet for at samle alle resultaterne i en Liste.

5. Konklusion

Vi har vist, hvordan man behandler en Kort på en funktionel måde.

Vi har især set, at når vi skifter til at bruge de tilknyttede samlinger til Korts, behandlingen ved hjælp af Strøms bliver meget lettere og intuitivt.

Og selvfølgelig kan alle eksemplerne findes i GitHub-projektet.