Guide til Guava Multiset

1. Oversikt

I denne opplæringen vil vi utforske en av Guava-samlingene - Multisett. Som en java.util.Sett, det muliggjør effektiv lagring og henting av varer uten en garantert ordre.

Imidlertid, i motsetning til en Sett, det tillater det flere forekomster av det samme elementet ved å spore antall hver unike element det inneholder.

2. Maven avhengighet

La oss først legge til guava avhengighet:

 com.google.guava guava 29.0-jre 

3. Bruke Multisett

La oss vurdere en bokhandel som har flere eksemplarer av forskjellige bøker. Vi vil kanskje utføre operasjoner som å legge til en kopi, få antall eksemplarer og fjerne en kopi når den er solgt. Som en Sett tillater ikke flere forekomster av det samme elementet, det kan ikke håndtere dette kravet.

La oss komme i gang med å legge til kopier av en boktittel. De Multisett skal returnere at tittelen eksisterer og gi oss riktig antall:

Multiset bookStore = HashMultiset.create (); bookStore.add ("Potter"); bookStore.add ("Potter"); bookStore.add ("Potter"); assertThat (bookStore.contains ("Potter")). isTrue (); assertThat (bookStore.count ("Potter")) er EqualTo (3);

La oss nå fjerne en kopi. Vi forventer at tellingen blir oppdatert tilsvarende:

bookStore.remove ("Potter"); assertThat (bookStore.contains ("Potter")). isTrue (); assertThat (bookStore.count ("Potter")). er EqualTo (2);

Og faktisk, vi kan bare angi tellingen i stedet for å utføre forskjellige tilleggsoperasjoner:

bookStore.setCount ("Potter", 50); assertThat (bookStore.count ("Potter")). er EqualTo (50);

Multisett validerer telle verdi. Hvis vi setter det til negativt, an IllegalArgumentException blir kastet:

assertThatThrownBy (() -> bookStore.setCount ("Potter", -1)) .isInstanceOf (IllegalArgumentException.class);

4. Sammenligning med Kart

Uten tilgang til Multisett, kunne vi oppnå alle operasjonene ovenfor ved å implementere vår egen logikk ved hjelp av java.util.Kart:

Map bookStore = ny HashMap (); // legge til 3 eksemplarer bookStore.put ("Potter", 3); assertThat (bookStore.containsKey ("Potter")). isTrue (); assertThat (bookStore.get ("Potter")). erEqualTo (3); // fjerne 1 kopi bookStore.put ("Potter", 2); assertThat (bookStore.get ("Potter")). er EqualTo (2);

Når vi vil legge til eller fjerne en kopi ved hjelp av en Kart, må vi huske gjeldende telling og justere den deretter. Vi må også implementere denne logikken i ringekoden hver gang eller konstruere vårt eget bibliotek for dette formålet. Koden vår vil også trenge å kontrollere verdi argument. Hvis vi ikke er forsiktige, kan vi enkelt sette verdien til null eller negativ selv om begge verdiene er ugyldige:

bookStore.put ("Potter", null); assertThat (bookStore.containsKey ("Potter")). isTrue (); bookStore.put ("Potter", -1); assertThat (bookStore.containsKey ("Potter")). isTrue (); 

Som vi kan se, er det mye mer praktisk å bruke Multisett i stedet for Kart.

5. Samtidighet

Når vi vil bruke Multisett i et samtidig miljø, kan vi bruke ConcurrentHashMultiset, som er en trådsikker Multisett gjennomføring.

Vi bør merke oss at det å være trådsikkert ikke garanterer konsistens. Bruker legge til eller fjerne metoder vil fungere bra i et miljø med flere tråder, men hva om flere tråder kalte setCount metode?

Hvis vi bruker setCount metode, det endelige resultatet vil avhenge av rekkefølgen på utførelsen på tvers av tråder, som ikke nødvendigvis kan forutsies. De legge til og fjerne metodene er inkrementelle, og ConcurrentHashMultiset er i stand til å beskytte sin oppførsel. Å sette tellingen direkte er ikke trinnvis, og det kan føre til uventede resultater når den brukes samtidig.

Imidlertid er det en annen smak av setCount metode som bare oppdaterer tellingen hvis den nåværende verdien samsvarer med det godkjente argumentet. Metoden blir sant hvis operasjonen lyktes, en form for optimistisk låsing:

Multiset bookStore = HashMultiset.create (); // oppdaterer tellingen til 2 hvis den nåværende tellingen er 0 assertThat (bookStore.setCount ("Potter", 0, 2)). isTrue (); // oppdaterer tellingen til 5 hvis den nåværende verdien er 50 assertThat (bookStore.setCount ("Potter", 50, 5)). isFalse ();

Hvis vi vil bruke setCount metode i samtidig kode, bør vi bruke ovennevnte versjon for å garantere konsistens. En klient med flere tråder kan utføre et nytt forsøk hvis endring av teller mislyktes.

6. Konklusjon

I denne korte opplæringen diskuterte vi når og hvordan du bruker en Flersett, sammenlignet den med en standard Kart og så på hvordan man best kan bruke den i en samtidig applikasjon.

Som alltid kan kildekoden for eksemplene finnes på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found