Útmutató a Guava Multiset-hez
1. Áttekintés
Ebben az oktatóanyagban felfedezzük az egyik guava-gyűjteményt - Multiset. Mint egy java.util.Set, lehetővé teszi az elemek hatékony tárolását és visszakeresését garantált megrendelés nélkül.
Azonban, ellentétben a Készlet, lehetővé teszi ugyanazon elem többszörös előfordulása az egyes egyedi elemek számának követésével.
2. Maven-függőség
Először tegyük hozzá a gujávafa függőség:
com.google.guava guava 29.0-jre
3. Használata Multiset
Vegyünk egy könyvesboltot, amely több példányban tartalmazza a különböző könyveket. Előfordulhat, hogy olyan műveleteket kíván végrehajtani, mint egy példány hozzáadása, a példányszám megszerzése és egy példány eltávolítása eladáskor. Mint a Készlet nem engedélyezi ugyanazon elem többszörös előfordulását, nem tudja kezelni ezt a követelményt.
Kezdjük hozzáadással könyvcím példányai. A Multiset vissza kell adnia a cím létezését, és meg kell adnia a helyes számot:
Multiset bookStore = HashMultiset.create (); bookStore.add ("Potter"); bookStore.add ("Potter"); bookStore.add ("Potter"); assertThat (bookStore.contains ("Potter")). isTrue (); assertThat (bookStore.count ("Potter")). isEqualTo (3);
Most távolítsunk el egy példányt. Arra számítunk, hogy a számlálás ennek megfelelően frissül:
bookStore.remove ("Potter"); assertThat (bookStore.contains ("Potter")). isTrue (); assertThat (bookStore.count ("Potter")). isEqualTo (2);
És valójában csak beállíthatjuk a számlálást különféle műveletek végrehajtása helyett:
bookStore.setCount ("Potter", 50); assertThat (bookStore.count ("Potter")). isEqualTo (50);
Multiset érvényesíti a számol érték. Ha negatívra állítjuk, akkor egy IllegalArgumentException dobják:
assertThatThrownBy (() -> bookStore.setCount ("Potter", -1)) .isInstanceOf (IllegalArgumentException.class);
4. Összehasonlítás Térkép
Hozzáférés nélkül Multiset, az összes fenti műveletet a saját logikánk használatával valósíthatnánk meg java.util.Térkép:
Térkép bookStore = új HashMap (); // 3 példány hozzáadása bookStore.put ("Potter", 3); assertThat (bookStore.containsKey ("Potter")). isTrue (); assertThat (bookStore.get ("Potter")). isEqualTo (3); // 1 példány eltávolítása bookStore.put ("Potter", 2); assertThat (bookStore.get ("Potter")). isEqualTo (2);
Amikor hozzá akarunk adni vagy eltávolítani egy példányt a használatával Térkép, emlékeznünk kell az aktuális számlálásra, és ennek megfelelően kell beállítanunk. Ezt a logikát minden alkalommal be kell építenünk a hívó kódunkba, vagy saját könyvtárat kell létrehoznunk erre a célra. A kódunknak is ellenőriznie kell a érték érv. Ha nem vagyunk óvatosak, könnyen beállíthatjuk az értéket nulla vagy negatív, még akkor is, ha mindkét érték érvénytelen:
bookStore.put ("Potter", null); assertThat (bookStore.containsKey ("Potter")). isTrue (); bookStore.put ("Potter", -1); assertThat (bookStore.containsKey ("Potter")). isTrue ();
Mint láthatjuk, sokkal kényelmesebb használni Multiset ahelyett Térkép.
5. Egyidejűség
Amikor használni akarjuk Multiset párhuzamos környezetben használhatjuk ConcurrentHashMultiset, ami szálbiztos Multiset végrehajtás.
Meg kell jegyeznünk, hogy a menetbiztonság nem garantálja a következetességet. Használni a hozzá vagy eltávolítani a módszerek jól működnek többszálas környezetben, de mi van, ha több szál hívja a setCount módszer?
Ha a setCount módszer, a végeredmény a szálak közötti végrehajtás sorrendjétől függ, amelyet nem feltétlenül lehet megjósolni. A hozzá és eltávolítani módszerek inkrementálisak, és a ConcurrentHashMultiset képes megvédeni viselkedésüket. A számlálás közvetlen beállítása nem növekményes, ezért váratlan eredményeket okozhat egyidejű használat esetén.
Van azonban egy másik íze is setCount módszer, amely csak akkor frissíti a számlálást, ha annak aktuális értéke megegyezik az átadott argumentummal. A módszer igaz, ha a művelet sikeres volt, az optimista zárolás egyik formája:
Multiset bookStore = HashMultiset.create (); // frissíti a számlálást 2-re, ha az aktuális szám 0 assertThat (bookStore.setCount ("Potter", 0, 2)). isTrue (); // frissíti a számlálást 5-re, ha az aktuális érték 50 assertThat (bookStore.setCount ("Potter", 50, 5)). isFalse ();
Ha használni akarjuk a setCount metódus párhuzamos kódban, a fenti verziót kell használnunk az egységesség garantálása érdekében. Egy többszálas kliens újrapróbálkozhat, ha a számlálás megváltoztatása sikertelen.
6. Következtetés
Ebben a rövid bemutatóban megvitattuk, mikor és hogyan kell használni a Multiset, összehasonlította egy standarddal Térkép és megnézte, hogyan lehet a legjobban használni egyidejű alkalmazásban.
Mint mindig, a példák forráskódja megtalálható a GitHub oldalon.