Fletning af to kort med Java 8
1. Introduktion
I denne hurtige vejledning vi demonstrerer, hvordan man fletter to kort ved hjælp af Java 8-funktionerne.
For at være mere specifik undersøger vi forskellige fletningsscenarier, herunder kort med duplikatposter.
2. Initialisering
Lad os som en start definere to Kort tilfælde:
privat statisk kort map1 = ny HashMap (); privat statisk kort map2 = ny HashMap ();
Det Medarbejder klasse ser sådan ud:
offentlig klassemedarbejder {privat Lang id; privat strengnavn; // konstruktør, getters, setters}
Derefter kan vi skubbe nogle data ind i Kort tilfælde:
Medarbejdermedarbejder1 = ny medarbejder (1L, "Henry"); map1.put (medarbejder1.getnavn (), medarbejder1); Medarbejdermedarbejder2 = ny medarbejder (22L, "Annie"); map1.put (medarbejder2.getnavn (), medarbejder2); Medarbejdermedarbejder3 = ny medarbejder (8L, "John"); map1.put (medarbejder3.getnavn (), medarbejder3); Medarbejdermedarbejder4 = ny medarbejder (2L, "George"); map2.put (medarbejder4.getnavn (), medarbejder4); Medarbejdermedarbejder5 = ny medarbejder (3L, "Henry"); map2.put (medarbejder5.getnavn (), medarbejder5);
Bemærk, at vi har identiske nøgler til medarbejder1 og medarbejder5 poster i vores kort, som vi bruger senere.
3. Map.merge ()
Java 8 tilføjer et nyt fusionere() funktion i java.util.Kort interface.
Her er hvordan fusionere() funktion fungerer: Hvis den angivne nøgle ikke allerede er knyttet til en værdi, eller værdien er nul, knytter den nøglen til den givne værdi.
Ellers erstatter den værdien med resultaterne af den givne remapping-funktion. Hvis resultatet af omknapningsfunktionen er nul, fjerner det resultatet.
Lad os først konstruere en ny HashMap ved at kopiere alle poster fra kort1:
Map map3 = nyt HashMap (map1);
Lad os derefter introducere fusionere() funktion sammen med fletningsregel:
map3.merge (nøgle, værdi, (v1, v2) -> ny medarbejder (v1.getId (), v2.getName ())
Endelig gentager vi over kort2 og flette posterne i kort3:
map2.forEach ((nøgle, værdi) -> map3.merge (nøgle, værdi, (v1, v2) -> ny medarbejder (v1.getId (), v2.getName ())));
Lad os køre programmet og udskrive indholdet af kort3:
John = Medarbejder {id = 8, navn = "John"} Annie = Medarbejder {id = 22, navn = "Annie"} George = Medarbejder {id = 2, navn = "George"} Henry = Medarbejder {id = 1, name = "Henry"}
Som resultat, vores kombinerede Kort har alle elementerne i det foregående HashMap poster. Indlæg med duplikatnøgler er blevet flettet til en post.
Vi bemærker også, at Medarbejder objektet for den sidste post har id fra kort1, og værdien er valgt fra kort2.
Dette skyldes den regel, vi definerede i vores fusionsfunktion:
(v1, v2) -> ny medarbejder (v1.getId (), v2.getName ())
4. Stream.concat ()
Det Strøm API i Java 8 kan også give en nem løsning på vores problem. Først, vi er nødt til at kombinere vores Kort tilfælde i en Strøm. Det er præcis hvad Stream.concat () operation gør:
Stream kombineret = Stream.concat (map1.entrySet (). Stream (), map2.entrySet (). Stream ());
Her passerer vi kortindgangssættene som parametre. Dernæst skal vi samle vores resultat til et nyt Kort. Til det kan vi bruge Collectors.toMap ():
Kortresultat = combined.collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue));
Som et resultat bruger samleren de eksisterende nøgler og værdier på vores kort. Men denne løsning er langt fra perfekt. Så snart vores samler møder poster med duplikatnøgler, kaster det en IllegalStateException.
For at håndtere dette problem tilføjer vi simpelthen en tredje "fusion" lambda-parameter i vores samler:
(værdi1, værdi2) -> ny medarbejder (værdi2.getId (), værdi1.getnavn ())
Det bruger lambda-udtrykket hver gang der identificeres en duplikatnøgle.
Endelig sætter alt sammen:
Kortresultat = Stream.concat (map1.entrySet (). Stream (), map2.entrySet (). Stream ()) .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (value1) , værdi2) -> ny medarbejder (værdi2.getId (), værdi1.getnavn ())));
Lad os endelig køre koden og se resultaterne:
George = Medarbejder {id = 2, navn = "George"} John = Medarbejder {id = 8, navn = "John"} Annie = Medarbejder {id = 22, navn = "Annie"} Henry = Medarbejder {id = 3, name = "Henry"}
Som vi ser, er de dobbelte poster med nøglen "Henry" blev slået sammen til et nyt nøgleværdipar hvor id for det nye Medarbejder blev plukket fra kort2 og værdien fra kort1.
5. Stream.of ()
For at fortsætte med at bruge Strøm API, vi kan vende vores Kort forekomster i en samlet strøm ved hjælp af Stream.of ().
Her behøver vi ikke oprette en ekstra samling for at arbejde med streams:
Map map3 = Stream.of (map1, map2) .flatMap (map -> map.entrySet (). Stream ()) .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (v1) , v2) -> ny medarbejder (v1.getId (), v2.getName ())));
Først, vi transformerer kort1 og kort2 ind i en enkelt strøm. Dernæst konverterer vi strømmen til kortet. Som vi kan se, er det sidste argument af at kortlægge() er en sammensmeltningsfunktion. Det løser problemet med duplikatnøgler ved at vælge id-feltet fra v1 post og navnet fra v2.
Den trykte kort3 instans efter at have kørt programmet:
George = Medarbejder {id = 2, navn = "George"} John = Medarbejder {id = 8, navn = "John"} Annie = Medarbejder {id = 22, navn = "Annie"} Henry = Medarbejder {id = 1, name = "Henry"}
6. Enkel streaming
Derudover kan vi bruge en strøm() rørledning til at samle vores kortindgange. Kodestykket nedenfor viser, hvordan du tilføjer poster fra kort2 og kort1 ved at ignorere de dobbelte poster:
Map map3 = map2.entrySet () .stream () .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (v1, v2) -> ny medarbejder (v1.getId (), v2 .getName ()), () -> nyt HashMap (kort1)));
Som vi forventer, er resultaterne efter fusionen:
{John = Medarbejder {id = 8, navn = "John"}, Annie = Medarbejder {id = 22, navn = "Annie"}, George = Medarbejder {id = 2, navn = "George"}, Henry = Medarbejder { id = 1, name = "Henry"}}
7. StreamEx
Ud over løsninger, der leveres af JDK, kan vi også bruge det populære StreamEx bibliotek.
Kort fortalt, StreamEx er en forbedring for Strøm API og giver mange yderligere nyttige metoder. Vi bruger en EntryStream instans til at operere på nøgleværdipar:
Map map3 = EntryStream.of (map1) .append (EntryStream.of (map2)) .toMap ((e1, e2) -> e1);
Ideen er at flette vores kortstrømme til en. Derefter samler vi posterne i det nye kort3 eksempel. Vigtigt at nævne, at (e1, e2) -> e1 udtryk, da det hjælper med at definere reglen til håndtering af duplikatnøgler. Uden det kaster vores kode en IllegalStateException.
Og nu, resultaterne:
{George = Medarbejder {id = 2, navn = "George"}, John = Medarbejder {id = 8, navn = "John"}, Annie = Medarbejder {id = 22, navn = "Annie"}, Henry = Medarbejder { id = 1, name = "Henry"}}
8. Resume
I denne korte artikel lærte vi forskellige måder at flette kort i Java 8. Mere specifikt, vi brugte Map.merge (), Stream API, StreamEx bibliotek.
Som altid kan koden, der blev brugt under diskussionen, findes på GitHub.