Gids voor Guava Multiset

1. Overzicht

In deze tutorial verkennen we een van de Guava-collecties - Multiset. Zoals een java.util.Set, het zorgt voor een efficiënte opslag en terugname van artikelen zonder een gegarandeerde bestelling.

In tegenstelling tot een Set, het staat toe meerdere exemplaren van hetzelfde element door de telling bij te houden van elk uniek element dat het bevat.

2. Maven Afhankelijkheid

Laten we eerst het guave afhankelijkheid:

 com.google.guava guave 29.0-jre 

3. Met behulp van Multiset

Laten we eens kijken naar een boekwinkel met meerdere exemplaren van verschillende boeken. We willen misschien bewerkingen uitvoeren zoals een kopie toevoegen, het aantal exemplaren ophalen en één exemplaar verwijderen wanneer het wordt verkocht. Als een Set staat niet toe dat hetzelfde element meerdere keren voorkomt, het kan deze vereiste niet aan.

Laten we beginnen door toe te voegen kopieën van een boektitel. De Multiset moet teruggeven dat de titel bestaat en ons het juiste aantal geven:

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

Laten we nu een kopie verwijderen. We verwachten dat de telling dienovereenkomstig wordt bijgewerkt:

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

En eigenlijk, we kunnen gewoon de telling instellen in plaats van verschillende toevoegbewerkingen uit te voeren:

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

Multiset valideert het tellen waarde. Als we het op negatief zetten, een IllegalArgumentException wordt gegooid:

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

4. Vergelijking met Kaart

Zonder toegang tot Multiset, zouden we alle bovenstaande bewerkingen kunnen uitvoeren door onze eigen logica te implementeren met behulp van java.util.Map:

Map bookStore = nieuwe HashMap (); // het toevoegen van 3 exemplaren bookStore.put ("Potter", 3); assertThat (bookStore.containsKey ("Potter")). isTrue (); assertThat (bookStore.get ("Potter")). isEqualTo (3); // verwijderen van 1 exemplaar bookStore.put ("Potter", 2); assertThat (bookStore.get ("Potter")). isEqualTo (2);

Wanneer we een kopie willen toevoegen of verwijderen met een Kaart, moeten we de huidige telling onthouden en deze dienovereenkomstig aanpassen. We moeten deze logica ook elke keer in onze aanroepcode implementeren of onze eigen bibliotheek voor dit doel construeren. Onze code zou ook het waarde argument. Als we niet oppassen, kunnen we de waarde gemakkelijk instellen op nul of negatief, hoewel beide waarden ongeldig zijn:

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

Zoals we kunnen zien, is het een stuk handiger in gebruik Multiset in plaats van Kaart.

5. Gelijktijdigheid

Wanneer we willen gebruiken Multiset in een gelijktijdige omgeving kunnen we ConcurrentHashMultiset, wat een thread-safe is Multiset implementatie.

We moeten echter opmerken dat thread-safe zijn geen garantie voor consistentie. De ... gebruiken toevoegen of verwijderen methoden zullen goed werken in een omgeving met meerdere threads, maar wat als verschillende threads de setCount methode?

Als we de setCount methode, het uiteindelijke resultaat zou afhangen van de volgorde van uitvoering over threads, wat niet noodzakelijkerwijs kan worden voorspeld. De toevoegen en verwijderen methoden zijn incrementeel, en de ConcurrentHashMultiset is in staat om hun gedrag te beschermen. Het rechtstreeks instellen van de telling is niet incrementeel en kan dus onverwachte resultaten opleveren bij gelijktijdig gebruik.

Er is echter nog een andere smaak van de setCount methode die de telling alleen bijwerkt als de huidige waarde overeenkomt met het doorgegeven argument. De methode retourneert true als de bewerking is geslaagd, een vorm van optimistische vergrendeling:

Multiset bookStore = HashMultiset.create (); // werkt de telling bij naar 2 als de huidige telling 0 is assertThat (bookStore.setCount ("Potter", 0, 2)). isTrue (); // werkt het aantal bij naar 5 als de huidige waarde 50 is assertThat (bookStore.setCount ("Potter", 50, 5)). isFalse ();

Als we de setCount methode in gelijktijdige code, moeten we de bovenstaande versie gebruiken om consistentie te garanderen. Een client met meerdere threads kan een nieuwe poging doen als het wijzigen van de telling is mislukt.

6. Conclusie

In deze korte tutorial hebben we besproken wanneer en hoe je een Multiset, vergeleken met een standaard Kaart en hebben gekeken hoe u het het beste in een gelijktijdige toepassing kunt gebruiken.

Zoals altijd is de broncode voor de voorbeelden te vinden op GitHub.