Arbeide med kart ved hjelp av strømmer

1. Introduksjon

I denne opplæringen vil vi diskutere noen eksempler på hvordan du bruker Java Strømså jobbe med Karts. Det er verdt å merke seg at noen av disse øvelsene kan løses ved hjelp av toveis Kart datastruktur, men vi er interessert her i en funksjonell tilnærming.

Først forklarer vi den grunnleggende ideen vi skal bruke til å jobbe med Kart og Strøms. Så presenterer vi et par forskjellige problemer knyttet til Kart og deres konkrete løsninger ved hjelp av Strøms.

2. Grunnleggende idé

Det viktigste å legge merke til er at Strøms er sekvenser av elementer som lett kan oppnås fra a Samling.

Kart ha en annen struktur, med en kartlegging fra nøkler til verdier, uten sekvens. Dette betyr ikke at vi ikke kan konvertere en Kart struktur i forskjellige sekvenser som deretter tillater oss å jobbe på en naturlig måte med Stream API.

La oss se måter å oppnå forskjellige på Samlings fra en Kart, som vi deretter kan svinge inn i Strøm:

Kartlegg someMap = nytt HashMap ();

Vi kan få et sett med nøkkelverdipar:

Sett oppføringer = someMap.entrySet ();

Vi kan også få nøkkelsettet tilknyttet Kart:

Set keySet = someMap.keySet ();

Eller vi kan jobbe direkte med verdisettet:

Samlingsverdier = someMap.values ​​();

Disse gir oss hvert et inngangspunkt for å behandle disse samlingene ved å skaffe strømmer fra dem:

Strøm entriesStream = entries.stream (); Strømverdier Strøm = verdier.strøm (); StrømnøklerStream = keySet.stream ();

3. Å få en Kart‘S Keys Using Strøms

3.1. Inndata

La oss anta at vi har en Kart:

Kartbøker = nytt HashMap (); books.put ("978-0201633610", "Design mønstre: elementer av gjenbrukbar objektorientert programvare"); books.put ("978-1617291999", "Java 8 in Action: Lambdas, Streams, and functional-style programmering"); books.put ("978-0134685991", "Effektiv Java");

Vi er interessert i å finne ISBN for boken med tittelen “Effektiv Java”.

3.2. Henter en kamp

Siden boktittelen ikke kunne eksistere i vår Kart, vi vil være i stand til å indikere at det ikke er noe tilknyttet ISBN for det. Vi kan bruke en Valgfri å uttrykke det:

La oss anta for dette eksemplet at vi er interessert i hvilken som helst nøkkel for en bok som samsvarer med den tittelen:

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

La oss analysere koden. Først, vi får tak i entrySet fra Kart, som vi så tidligere.

Vi vil bare vurdere oppføringene med “Effektiv Java” som tittel, så den første mellomoperasjonen vil være et filter.

Vi er ikke interessert i helheten Kart oppføring, men i nøkkelen til hver oppføring. Så, den neste kjedede mellomoperasjonen gjør nettopp det: det er en kart operasjon som vil generere en ny strøm som utdata som bare inneholder nøklene for oppføringene som samsvarte med tittelen vi lette etter.

Siden vi bare vil ha ett resultat, kan vi bruke findFirst () terminaloperasjon, som vil gi den opprinnelige verdien i Strøm som en Valgfri gjenstand.

La oss se et tilfelle der en tittel ikke eksisterer:

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

3.3. Henter flere resultater

La oss endre problemet nå for å se hvordan vi kan håndtere å returnere flere resultater i stedet for ett.

For å få returnert flere resultater, la oss legge til følgende bok i vår Kart:

books.put ("978-0321356680", "Effective Java: Second Edition"); 

Så nå, hvis vi ser etter alle bøker som starter med “Effektiv Java”, får vi mer enn ett resultat tilbake:

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"));

Det vi har gjort i dette tilfellet er å erstatte filtertilstanden for å verifisere om verdien i Kart starter med “Effektiv Java” i stedet for å sammenligne for String likestilling.

Denne gangen, vi samle inn resultatene - i stedet for å plukke den første - sette kampene i en Liste.

4. Å få en Kart‘S Verdier som bruker Strøms

La oss nå fokusere på et annet problem med kart: I stedet for å skaffe ISBN-er basert på titler, vi prøver å få titler basert på ISBN-er.

La oss bruke originalen Kart. Vi ønsker å finne titler som ISBN-nummeret deres begynner 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. inneholder ("Designmønstre: elementer av gjenbrukbar objektorientert programvare")); assertTrue (titler. inneholder ("Effektiv Java"));

Denne løsningen ligner på løsningene til vårt forrige sett med problemer - vi strømmer inngangssettet, og filtrerer, kartlegger og samler inn.

Og som før, hvis vi bare ønsket å returnere den første kampen, kunne vi etter kart metoden kaller findFirst () metode i stedet for å samle alle resultatene i en Liste.

5. Konklusjon

Vi har vist hvordan vi behandler en Kart på en funksjonell måte.

Spesielt har vi sett at når vi bytter til å bruke de tilknyttede samlingene til Karts, behandlingen ved hjelp Strøms blir mye lettere og intuitivt.

Og selvfølgelig kan alle eksemplene bli funnet i GitHub-prosjektet.