Két térkép egyesítése Java 8-tal

1. Bemutatkozás

Ebben a gyors bemutatóban bemutatjuk, hogyan lehet két térképet egyesíteni a Java 8 képességekkel.

Pontosabban: különféle egyesítési forgatókönyveket vizsgálunk meg, beleértve a duplikált bejegyzéseket tartalmazó térképeket is.

2. Inicializálás

Kezdésként definiáljunk kettőt Térkép példányok:

privát statikus Map map1 = új HashMap (); privát statikus Map map2 = új HashMap ();

A Munkavállaló osztály így néz ki:

public class Alkalmazott {private Long id; privát karakterlánc neve; // kivitelező, getters, setters}

Ezután néhány adatot betolhatunk a Térkép példányok:

Alkalmazott alkalmazott1 = új alkalmazott (1L, "Henry"); map1.put (alkalmazott1.getNév (), alkalmazott1); Alkalmazott alkalmazott2 = új alkalmazott (22L, "Annie"); map1.put (alkalmazott2.getNév (), alkalmazott2); Alkalmazott alkalmazott3 = új alkalmazott (8L, "John"); map1.put (alkalmazott3.getName (), alkalmazott3); Alkalmazott alkalmazott4 = új alkalmazott (2L, "George"); map2.put (alkalmazott4.getName (), alkalmazott4); Alkalmazott alkalmazott5 = új alkalmazott (3L, "Henry"); map2.put (alkalmazott5.getName (), alkalmazott5);

Ne feledje, hogy a alkalmazott1 és alkalmazott5 bejegyzések a térképeinken, amelyeket később felhasználunk.

3. Map.merge ()

A Java 8 hozzáad egy újat összeolvad() funkció az java.util.Térkép felület.

Itt van, hogyan összeolvad() függvény működik: Ha a megadott kulcs még nincs társítva egy értékhez, vagy az érték null, akkor a kulcsot az adott értékhez társítja.

Ellenkező esetben az értéket az adott újratervezési függvény eredményeivel helyettesíti. Ha az újratervezési függvény eredménye nulla, akkor az eredményt eltávolítja.

Először készítsünk egy újat HashMap az összes bejegyzés átmásolásával a térkép1:

Map map3 = új HashMap (map1);

Ezután mutassuk be a összeolvad() függvény az egyesítés szabályával együtt:

map3.merge (kulcs, érték, (v1, v2) -> új alkalmazott (v1.getId (), v2.getName ())

Végül iterálunk a térkép2 és egyesítse a bejegyzéseket térkép3:

map2.forEach ((kulcs, érték) -> map3.merge (kulcs, érték, (v1, v2) -> új alkalmazott (v1.getId (), v2.getName ())));

Futtassuk a programot és nyomtassuk ki a tartalmát térkép3:

John = Alkalmazott {id = 8, név = "John"} Annie = Alkalmazott {id = 22, név = "Annie"} George = Alkalmazott {id = 2, név = "George"} Henry = Alkalmazott {id = 1, név = "Henry"}

Ennek eredményeként a mi kombinált Térkép rendelkezik az előző összes elemével HashMap bejegyzés. Az ismétlődő kulcsokkal rendelkező bejegyzéseket egy bejegyzésbe egyesítették.

Azt is észrevesszük, hogy a Munkavállaló Az utolsó bejegyzés objektumának van id tól térkép1, és az értéket választják térkép2.

Ennek oka az egyesülési függvényben definiált szabály:

(v1, v2) -> új alkalmazott (v1.getId (), v2.getName ())

4. Stream.concat ()

A Folyam A Java 8-ban lévő API szintén egyszerű megoldást kínál a problémánkra. Első, kombinálnunk kell a mi Térkép példányok egybe Folyam. Pontosan ez az Stream.concat () művelet:

Kombinált adatfolyam = Stream.concat (map1.entrySet (). Stream (), map2.entrySet (). Stream ());

Itt adjuk meg a térképbejegyzési készleteket paraméterként. Ezután egy új eredményt kell összegyűjtenünk Térkép. Erre használhatjuk Collectors.toMap ():

Térkép eredménye = combined.collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue));

Ennek eredményeként a gyűjtő felhasználja térképeink meglévő kulcsait és értékeit. De ez a megoldás korántsem tökéletes. Amint gyűjtőnk találkozik a duplikált kulcsokkal ellátott bejegyzésekkel, dob egy IllegalStateException.

A probléma kezeléséhez egyszerűen hozzáadunk egy harmadik „egyesítési” lambda paramétert a gyűjtőnkbe:

(érték1, érték2) -> új alkalmazott (érték2.getId (), érték1.getName ())

Minden alkalommal használja a lambda kifejezést, amikor duplikált kulcsot észlel.

Végül az összes összeállítása:

Térkép eredménye = Stream.concat (map1.entrySet (). Stream (), map2.entrySet (). Stream ()) .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (value1) , value2) -> new Employee (value2.getId (), value1.getName ())));

Végül futtassuk a kódot, és nézzük meg az eredményeket:

George = Employee {id = 2, name = "George"} John = Employee {id = 8, name = "John"} Annie = Employee {id = 22, name = "Annie"} Henry = Employee {id = 3, név = "Henry"}

Mint látjuk, a duplikált bejegyzések a kulccsal "Henrik" egyesültek egy új kulcs-érték párba, ahol az új azonosítója Munkavállaló kiszedték a térkép2 és az értéke térkép1.

5. Stream.of ()

A tovább használatához Folyam API, megfordíthatjuk Térkép példányok egységes folyamba a Stream.of ().

Itt nem kell további gyűjteményt létrehoznunk a folyamok kezeléséhez:

Map map3 = Stream.of (map1, map2) .flatMap (térkép -> map.entrySet (). Stream ()) .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (v1) , v2) -> new Employee (v1.getId (), v2.getName ())));

Első, átalakulunk térkép1 és térkép2 egyetlen folyamba. Ezután átalakítjuk a folyamot térképpé. Mint láthatjuk, a térképre() egy összevonó függvény. Megoldja a duplikált kulcsok problémáját azáltal, hogy kiválasztja az id mezőt v1 bejegyzést és a nevet v2.

A nyomtatott térkép3 példány a program futtatása után:

George = Employee {id = 2, name = "George"} John = Employee {id = 8, name = "John"} Annie = Employee {id = 22, name = "Annie"} Henry = Employee {id = 1, név = "Henry"}

6. Egyszerű közvetítés

Ezenkívül használhatjuk a folyam() csővezeték a térképbejegyzéseink összeállításához. Az alábbi kódrészlet bemutatja, hogyan lehet hozzáadni a bejegyzéseket térkép2 és térkép1 az ismétlődő bejegyzések figyelmen kívül hagyásával:

Map map3 = map2.entrySet () .stream () .collect (Collectors.toMap (Map.Entry :: getKey, Map.Entry :: getValue, (v1, v2) -> new Employee (v1.getId (), v2 .getName ()), () -> új HashMap (térkép1)));

Amint arra számítunk, az egyesítés után az eredmények a következők:

{John = Employee {id = 8, name = "John"}, Annie = Employee {id = 22, name = "Annie"}, George = Employee {id = 2, name = "George"}, Henry = Employee { id = 1, név = "Henry"}}

7. StreamEx

A JDK által nyújtott megoldások mellett használhatjuk a népszerűt is StreamEx könyvtár.

Egyszerűen fogalmazva, StreamEx továbbfejlesztése a Folyam API és számos további hasznos módszert nyújt. Használunk egy EntryStream például kulcs-érték párok működtetésére:

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

Az ötlet az, hogy a térképeink folyamait egyesítsük egybe. Ezután összegyűjtjük a bejegyzéseket az újba térkép3 példa. Fontos megemlíteni, hogy (e1, e2) -> e1 kifejezés, mivel segít meghatározni a duplikált kulcsok kezelésének szabályát. Enélkül a kódunk dob egy IllegalStateException.

És most, az eredmények:

{George = Employee {id = 2, name = "George"}, John = Employee {id = 8, name = "John"}, Annie = Employee {id = 22, name = "Annie"}, Henry = Employee { id = 1, név = "Henry"}}

8. Összefoglalás

Ebben a rövid cikkben megtanultuk a térképek egyesítésének különböző módjait a Java 8-ban. használtuk Map.merge (), Stream API, StreamEx könyvtár.

Mint mindig, a vita során használt kód megtalálható a GitHubon.