Ú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.