Spajanje dviju karata s Javom 8

1. Uvod

U ovom brzom vodiču, pokazat ćemo kako spojiti dvije mape pomoću Java 8 mogućnosti.

Da bismo bili precizniji, ispitati ćemo različite scenarije spajanja, uključujući karte s dupliciranim unosima.

2. Inicijalizacija

Za početak definirajmo dvije Karta primjerci:

privatna statička karta map1 = novi HashMap (); privatna statička karta map2 = novi HashMap ();

The Zaposlenik razred izgleda ovako:

zaposlenik u javnoj klasi {private Long id; privatni naziv niza; // konstruktor, getteri, postavljači}

Zatim možemo gurnuti neke podatke u Karta primjerci:

Zaposlenik zaposlenik1 = novi zaposlenik (1L, "Henry"); map1.put (zaposlenik1.getName (), zaposlenik1); Zaposlenik zaposlenik2 = novi zaposlenik (22L, "Annie"); map1.put (zaposlenik2.getName (), zaposlenik2); Zaposlenik zaposlenik3 = novi zaposlenik (8L, "John"); map1.put (zaposlenik3.getName (), zaposlenik3); Zaposlenik zaposlenik4 = novi zaposlenik (2L, "George"); map2.put (zaposlenik4.getName (), zaposlenik4); Zaposlenik zaposlenik5 = novi zaposlenik (3L, "Henry"); map2.put (zaposlenik5.getName (), zaposlenik5);

Imajte na umu da imamo identične ključeve za zaposlenik1 i zaposlenik5 unose na našim kartama koje ćemo koristiti kasnije.

3. Map.merge ()

Java 8 dodaje novi sjediniti() funkcioniraju u java.util.Map sučelje.

Evo kako sjediniti() funkcija radi: Ako navedeni ključ već nije pridružen vrijednosti ili je vrijednost null, pridružuje ključ zadanoj vrijednosti.

Inače, vrijednost zamjenjuje rezultatima zadane funkcije preslikavanja. Ako je rezultat funkcije preslikavanja nula, uklanja rezultat.

Prvo, konstruirajmo novo HashMap kopiranjem svih unosa iz karta1:

Map map3 = novi HashMap (map1);

Dalje, predstavimo sjediniti() funkcija zajedno s pravilom spajanja:

map3.merge (ključ, vrijednost, (v1, v2) -> novi zaposlenik (v1.getId (), v2.getName ())

Napokon ćemo ponoviti karta2 i spojite unose u karta3:

map2.forEach ((ključ, vrijednost) -> map3.merge (ključ, vrijednost, (v1, v2) -> novi zaposlenik (v1.getId (), v2.getName ())));

Pokrenimo program i ispišite sadržaj karta3:

John = Zaposlenik {id = 8, name = "John"} Annie = Zaposlenik {id = 22, name = "Annie"} George = Zaposlenik {id = 2, name = "George"} Henry = Zaposlenik {id = 1, name = "Henry"}

Kao rezultat, naša kombinirana Karta ima sve elemente prethodnog HashMap unosi. Unosi s dupliciranim ključevima spojeni su u jedan unos.

Također, primjećujemo da Zaposlenik objekt zadnjeg unosa ima iskaznica od karta1, a vrijednost se bira iz karta2.

To je zbog pravila koje smo definirali u našoj funkciji spajanja:

(v1, v2) -> novi zaposlenik (v1.getId (), v2.getName ())

4. Stream.concat ()

The Stream API u Javi 8 također može pružiti jednostavno rješenje za naš problem. Prvi, moramo kombinirati svoje Karta instance u jedan Stream. Upravo to Stream.concat () operacija radi:

Kombinirani tok = Stream.concat (map1.entrySet (). Stream (), map2.entrySet (). Stream ());

Ovdje kao parametre prosljeđujemo skupove unosa karte. Dalje, moramo prikupiti naš rezultat u novi Karta. Za to možemo koristiti Collectors.toMap ():

Rezultat karte = kombinirano.collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue));

Kao rezultat toga, sakupljač će koristiti postojeće ključeve i vrijednosti naših karata. Ali ovo rješenje daleko je od savršenstva. Čim naš sakupljač upozna unose s dupliciranim ključevima, bacit će znak IllegalStateException.

Da bismo riješili ovaj problem, jednostavno dodajemo treći lambda parametar "spajanje" u naš sakupljač:

(value1, value2) -> novi zaposlenik (value2.getId (), value1.getName ())

Upotrijebit će lambda izraz svaki put kad se otkrije duplicirani ključ.

Konačno, stavljajući sve zajedno:

Rezultat karte = Stream.concat (map1.entrySet (). Stream (), map2.entrySet (). Stream ()) .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (value1 , value2) -> novi zaposlenik (value2.getId (), value1.getName ())));

Na kraju, pokrenimo kod i vidjet ćemo rezultate:

George = Zaposlenik {id = 2, name = "George"} John = Zaposlenik {id = 8, name = "John"} Annie = Zaposlenik {id = 22, name = "Annie"} Henry = Zaposlenik {id = 3, name = "Henry"}

Kao što vidimo, duplicirani unosi s ključem "Henry" bili spojeni u novi par ključ / vrijednost gdje id novog Zaposlenik je odabran iz karta2 a vrijednost od karta1.

5. Stream.of ()

Da biste nastavili koristiti Stream API, možemo okrenuti svoj Karta instanci u jedinstveni tok uz pomoć Stream.of ().

Ovdje ne moramo stvoriti dodatnu kolekciju za rad sa streamovima:

Map map3 = Stream.of (map1, map2) .flatMap (map -> map.entrySet (). Stream ()) .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (v1 , v2) -> novi zaposlenik (v1.getId (), v2.getName ())));

Prvi, transformiramo karta1 i karta2 u jedan tok. Zatim pretvaramo tok u kartu. Kao što vidimo, posljednji argument toMap () je funkcija spajanja. Riješava problem dupliciranih ključeva odabirom polja id v1 unos i naziv iz v2.

Tiskano karta3 instanca nakon pokretanja programa:

George = Zaposlenik {id = 2, name = "George"} John = Zaposlenik {id = 8, name = "John"} Annie = Zaposlenik {id = 22, name = "Annie"} Henry = Zaposlenik {id = 1, name = "Henry"}

6. Jednostavno strujanje

Uz to možemo koristiti i stream () cjevovod za prikupljanje unosa na našoj karti. Isječak koda u nastavku pokazuje kako dodati unose iz karta2 i karta1 zanemarivanjem dvostrukih unosa:

Karta map3 = map2.entrySet () .stream () .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (v1, v2) -> novi zaposlenik (v1.getId (), v2 .getName ()), () -> nova HashMap (karta1)));

Kao što i očekujemo, rezultati nakon spajanja su:

{John = Zaposlenik {id = 8, name = "John"}, Annie = Zaposlenik {id = 22, name = "Annie"}, George = Zaposlenik {id = 2, name = "George"}, Henry = Zaposlenik { id = 1, name = "Henry"}}

7. StreamEx

Pored rješenja koja pruža JDK, možemo se poslužiti i popularnim StreamEx knjižnica.

Jednostavno rečeno, StreamEx je poboljšanje za Stream API i pruža mnoge dodatne korisne metode. Upotrijebit ćemo EntryStream primjerice za rad na parovima ključ / vrijednost:

Map map3 = EntryStream.of (map1) .append (EntryStream.of (map2)) .toMap ((e1, e2) -> e1);

Ideja je spojiti tokove naših karata u jedno. Zatim prikupljamo unose u novo karta3 primjer. Važno je spomenuti, (e1, e2) -> e1 izraz pomaže u definiranju pravila za postupanje s duplikatima ključeva. Bez toga će naš kod baciti znak IllegalStateException.

A sada, rezultati:

{George = Zaposlenik {id = 2, name = "George"}, John = Zaposlenik {id = 8, name = "John"}, Annie = Zaposlenik {id = 22, name = "Annie"}, Henry = Zaposlenik { id = 1, name = "Henry"}}

8. Sažetak

U ovom kratkom članku naučili smo različite načine spajanja karata u Javi 8. Točnije, koristili smo Map.merge (), Stream API, StreamEx knjižnica.

Kao i uvijek, kod korišten tijekom rasprave možete pronaći na GitHubu.