Kaart van primitieven in Java

1. Overzicht

In deze tutorial leren we hoe je een kaart maakt met primitieve sleutels en waarden.

Zoals we weten, de kern Java Kaarts staan ​​de opslag van primitieve sleutels of waarden niet toe. Daarom introduceren we enkele externe bibliotheken van derden die primitieve kaartimplementaties bieden.

2. Eclipse-collecties

Eclipse Collections is een hoogwaardig verzamelframework voor Java. Het biedt verbeterde implementaties en enkele aanvullende gegevensstructuren, waaronder verschillende primitieve collecties.

2.1. Veranderlijk en onveranderlijk Kaarten

Laten we een lege kaart maken waarin zowel sleutels als waarden primitief zijn ints. Daarvoor gebruiken we de IntIntMaps fabrieksklasse:

MutableIntIntMap mutableIntIntMap = IntIntMaps.mutable.empty ();

De IntIntMaps factory class is de handigste manier om primitieve kaarten te maken. Het stelt ons in staat om zowel veranderlijke als onveranderlijke instanties van het gewenste type kaart te creëren. In ons voorbeeld hebben we de veranderlijke instantie van IntIntMap. Evenzo kunnen we een onveranderlijke instantie maken door simpelweg de IntIntMaps.mutable statische fabrieksoproep met IntIntMaps. Onveranderlijk:

ImmutableIntIntMap immutableIntIntMap = IntIntMaps.immutable.empty ();

Laten we dus een sleutel / waarde-paar toevoegen aan onze veranderlijke kaart:

mutableIntIntMap.addToValue (1, 1);

Hetzelfde, we kunnen gemengde kaarten maken met referentie- en primitieve sleutel-waardeparen. Laten we een kaart maken met Draad sleutels en dubbele waarden:

MutableObjectDoubleMap dObject = ObjectDoubleMaps.mutable.empty ();

Hier hebben we de ObjectDoubleMaps factory class om een ​​veranderlijke instantie voor te maken MutableObjectDoubleMap.

Laten we nu een paar items toevoegen:

dObject.addToValue ("prijs", 150,5); dObject.addToValue ("kwaliteit", 4.4); dObject.addToValue ("stabiliteit", 0,8);

2.2. Een primitieve API-structuur

In Eclipse Collections is er een basisinterface met de naam PrimitiveIterable. Dit is de basisinterface voor elk van de primitieve containers van de bibliotheek. Ze zijn allemaal genoemd PrimitiveTypeIterable, waar PrimitiveType kan zijn Int, Long, Kort, Byte, Char, Vlotter, Dubbele, of Boolean.

Al deze basisinterfaces hebben op hun beurt hun boomstructuur XYKaart implementaties, dat is verdeeld over de vraag of de kaart veranderlijk of onveranderlijk is. Als voorbeeld voor IntIntMap, we hebben MutableIntIntMap en ImmutableIntIntMap.

Eindelijk, zoals we hierboven zagen, hebben we interfaces om allerlei combinaties van typen voor sleutels en waarden voor zowel primitieve als objectwaarden te dekken. Dus we kunnen bijvoorbeeld hebben IntObjectMap voor een primitieve sleutel met een Voorwerp waarde of ObjectIntMap voor het tegenovergestelde geval.

3. HPPC

HPPC is een bibliotheek die gericht is op hoge prestaties en geheugenefficiëntie. Dit betekent dat de bibliotheek minder abstractie heeft dan andere. Dit heeft echter het voordeel dat de interne onderdelen worden blootgesteld aan nuttige manipulatie op laag niveau. Het biedt zowel kaarten als sets.

3.1. Een eenvoudig voorbeeld

Laten we beginnen met het maken van een kaart met een int sleutel en een lang waarde. Het gebruik hiervan is redelijk bekend:

IntLongHashMap intLongHashMap = nieuwe IntLongHashMap (); intLongHashMap.put (25, 1L); intLongHashMap.put (150, Long.MAX_VALUE); intLongHashMap.put (1, 0L); intLongHashMap.get (150);

HPPC biedt kaarten voor alle combinaties van sleutels en waarden:

  • Primitieve sleutel en primitieve waarde
  • Primitieve sleutel en objecttype waarde
  • Objecttype sleutel en primitieve waarde
  • Zowel objecttype sleutel als waarde

Object-type kaarten ondersteunen generieke gegevens:

IntObjectOpenHashMap ObjectIntOpenHashMap 

De eerste kaart heeft een primitief int sleutel en een BigDecimal waarde. De tweede kaart heeft LocalDate voor zijn sleutels en int voor zijn waarden

3.2. Hash-kaarten versus verspreide kaarten

Vanwege de manier waarop belangrijke hashing- en distributiefuncties traditioneel worden geïmplementeerd, kunnen er botsingen optreden bij het hashen van de sleutels. Afhankelijk van hoe sleutels worden gedistribueerd, kan dit leiden tot prestatieproblemen op grote kaarten. HPPC implementeert standaard een oplossing die dit probleem vermijdt.

Er is echter nog steeds een plaats voor kaarten die een eenvoudigere distributiefunctie hebben. Dit is handig als de kaarten worden gebruikt als opzoektabellen of om te tellen, of als ze niet veel schrijfbewerkingen vereisen nadat ze zijn geladen. HHPC biedt Verspreid kaarten om de prestaties nog meer te verbeteren.

Alle scatter-mapklassen behouden dezelfde naamgevingsconventie als kaarten, maar gebruiken in plaats daarvan het woord Verstrooien:

  • IntScatterSet
  • IntIntScatterMap
  • IntObjectScatterMap

4. Fastutil

Fastutil is een snel en compact framework die typespecifieke verzamelingen biedt, inclusief primitieve typekaarten.

4.1. Snel voorbeeld

Vergelijkbaar met Eclipse Collections en HPPC. Fastutil biedt ook primitief-naar-primitieve en primitief-naar-object getypeerde associatiekaarten.

Laten we een int naar boolean kaart:

Int2BooleanMap int2BooleanMap = nieuwe Int2BooleanOpenHashMap ();

En laten we nu wat vermeldingen toevoegen:

int2BooleanMap.put (1, true); int2BooleanMap.put (7, false); int2BooleanMap.put (4, true);

Vervolgens kunnen we er waarden uit halen:

booleaanse waarde = int2BooleanMap.get (1);

4.2. In-Place iteratie

Standaard JVM-verzamelingen die het Herhaalbaar interface maakt meestal bij elke iteratiestap een nieuw tijdelijk iteratorobject. Bij enorme collecties kan dit een probleem met het ophalen van afval veroorzaken.

Fastutil biedt een alternatief dat dit sterk vermindert:

Int2FloatMap map = nieuwe Int2FloatMap (); // Voeg hier sleutels toe voor (Int2FloatMap.Entry e: Fastutil.fastIterable (map)) {// e wordt bij elke iteratie opnieuw gebruikt, dus het is slechts één object} 

Fastutil biedt ook de fastForeach methode. Dit duurt een Klant functionele interface en voer een lambda-uitdrukking uit voor elke lus:

Int2FloatMap map = nieuwe Int2FloatMap (); // Voeg hier sleutels toe Int2FloatMaps.fastForEach (map, e -> {// e wordt ook hergebruikt in iteraties}); 

Dit lijkt erg op de standaard Java voor elk construeren:

Int2FloatMap map = nieuwe Int2FloatMap (); // Voeg hier sleutels toe map.forEach ((sleutel, waarde) -> {// gebruik elke sleutel / waarde-invoer}); 

5. Conclusie

In dit artikel hebben we geleerd hoe maak primitieve kaarten in Java met behulp van Eclipse Collections, HPPC en Fastutil.

Zoals altijd is de voorbeeldcode voor dit artikel beschikbaar op GitHub.