Mapa de Primitivas em Java

Mapa de Primitivas em Java

 1. Visão geral

Neste tutorial, aprenderemoshow to construct a map with primitive keys and values.

Como sabemos, o JavaMaps principal não permite o armazenamento de chaves ou valores primitivos. É por isso que vamos apresentar uma série de bibliotecas externas de terceiros que fornecem implementações de mapas primitivos.

2. Coleções Eclipse

Resumindo,Eclipse Collections is a high-performance collection framework for Java. Ele fornece implementações aprimoradas, bem como algumas estruturas de dados adicionais, incluindoa number of primitive collections.

Mais especificamente, existem implementações mutáveis, imutáveis ​​e não modificáveis ​​de um mapa primitivo.

2.1. Mutável e imutávelMaps

Vamos criar um mapa vazio onde a chave e o valor sãoints primitivos. Para isso, usaremos a classe de fábricaIntIntMaps:

MutableIntIntMap mutableIntIntMap = IntIntMaps.mutable.empty();

The IntIntMaps factory class is the most convenient way to create primitive maps. Isso nos permite criar instâncias mutáveis ​​e imutáveis ​​do tipo de mapa desejado. Em nosso exemplo, criamos a instância mutável deIntIntMap. Da mesma forma, podemos criar uma instância imutável simplesmente substituindo a chamada de fábrica estáticaIntIntMaps.mutable porIntIntMaps.immutable:

ImmutableIntIntMap immutableIntIntMap = IntIntMaps.immutable.empty();

Então, vamos adicionar um par de chave e valor ao nosso mapa mutável:

mutableIntIntMap.addToValue(1, 1);

Da mesma forma,we can create mixed maps with reference and primitive type key-value pairs. Vamos criar um mapa com as chavesStringe valoresdouble:

MutableObjectDoubleMap dObject = ObjectDoubleMaps.mutable.empty();

Aqui, usamos a classe de fábricaObjectDoubleMaps para criar uma instância mutável paraMutableObjectDoubleMap.

Agora vamos adicionar algumas entradas:

dObject.addToValue("price", 150.5);
dObject.addToValue("quality", 4.4);
dObject.addToValue("stability", 0.8);

2.2. Uma árvore API primitiva

Em Eclipse Collections,PrimitiveIterable é a interface base para todos os contêineres primitivos, incluindo aqueles paraMap. Além disso, cada tipo primitivo possui sua própria interface de base derivada dePrimitiveIterable.

Por exemplo, a interface de baseShortIterable é para o tipo primitivoshort eLongIterable é para o tipo primitivolong. Da mesma forma, para os tiposint, byte, float, double, booleanos echar, as interfaces básicas sãoIntIterable, ByteIterable, FloatIterable, DoubleIterable, BooleanIterable,eCharIterable,  respectivamente.

Todas essas interfaces básicas têm sua própria árvore de implementações deXYMap:

First, each interface has two kinds of implementations, mutable and immutable. Acabamos de ver isso comIntIntMap,MutableIntIntMap eImmutableIntIntMap.

Em segundo lugar, todas essas implementações de mapas primitivos têmall the combinations between their primitive and the rest of the primitive types. Então, paraint, temosFloatIntMap – e suas implementações mutáveis ​​e imutáveis ​​- mas também temosIntFloatMap.

Finalmente, como vimos há pouco, temosinterfaces for mixing primitive and reference types. Paraint, obtemosObjectIntMap<K> para misturar uma chaveObject com um tipo primitivo e o inverso,IntObjectMap<K>, para misturar uma chave primitiva com um valorObject . K,, é claro, é o tipo de referência para o objeto necessário.

3. Trove

Trove is another high-performance library which provides primitive collections for Java.

3.1. Começo rápido

Em primeiro lugar, vamos criar um mapa primitivo aceitando chaves de tipodouble e valoresint:

TDoubleIntMap doubleIntMap = new TDoubleIntHashMap();

Então, vamos adicionar algumas entradas:

doubleIntMap.put(1.2, 22);
doubleIntMap.put(4.5, 16);

3.2. Entradas ajustáveis

Um recurso interessante no Trove éthe ability to adjust entry values.

Agora, quando temos um mapa com chaves e valores, podemos ajustar algumas entradas:

doubleIntMap.adjustValue(1.2, 1);
doubleIntMap.adjustValue(4.5, 4);
doubleIntMap.adjustValue(0.3, 7);

Aqui, as duas primeiras operações aumentarão as teclas1.2e4.5 com unidades1e4. No entanto, o último ajusteValor () retornaráfalse sem efeito. Isso ocorre porque simplesmente não temos nenhuma entrada com uma chave0.3.

3.3. Construtores completos

Todos nós experimentamosthe pain of constructing a Map in Java, need para chamar o construtor e, em seguida, fornecer os elementos separadamente.

Com o Trove, se conhecermos as chaves e os valores antecipadamente, podemos fornecer os valores como um argumento construtor. Primeiro, vamos definir a matriz de chaves:

double[] doubles = new double[] {1.2, 4.5, 0.3};

Em seguida, os valores:

int[] ints = new int[] {1, 4, 0};

Por fim, passamos para o construtor:

TDoubleIntMap doubleIntMap = new TDoubleIntHashMap(doubles, ints);

3.4. Folha de dicas

Junto com todos os métodos padrão disponíveis nas implementaçõesMap do JDK, Trove fornece alguns métodos mais úteis:

  • putIfAbsent(key, value) - adiciona a chave, a entrada de valor apenas se o mapa não contiver a chave

  • adjustOrPutValue(key, adjust_amount, put_amount) - ondeput_amount é o valor inicial,adjust_amount é a quantidade de incremento

  • adjustValue(key, amount) - é semelhante aadjustOrPutValue() com uma exceção: não configura o valor inicial. Então, se não tivermos nenhuma associação com okey fornecido,adjustValue() não mudará nada e retornaráfalse

  • increment(key) - chama internamente oadjustValue(key, 1)

  • retainEntries(TDoubleIntProcedure) - retém apenas as entradas que satisfazem o procedimento

O pacotegnu.trove.map contém todas as interfaces para trabalhar com mapas primitivos. Além disso, podemos usar todas as combinações da chave, pares de valores como:

  • A primitive key and primitive value – por exemplo, a interfaceTDoubleIntMap é um mapa primitivo da chavedoublee do valorint

  • A primitive key and Object value –TByteObjectMap<T> pode ter uma chavebytee tipo de referência deT

  • E, finalmente,an Object key and primitive value –TObjectByteMap<T>  é um mapa primitivo deT digiteObject chaves e valoresbyte

Sob o capô, todos os mapas primitivos têm três contêineres primitivos para armazenar os dados:

  • _values[] - mantém os valores primitivos

  • _set[] - contém as primitivas de chave

  • _states[] – mantém o estado da célula - livre, ocupada, excluída

4. Colt

Colt é uma biblioteca de código aberto para computação científica e técnica em Java.

4.1. Um Equivalente Simples

Colt brilha comoa simple primitive-to-primitive equivalent to Java’s Map interface.

Primeiro, vamos criar um mapa de associação deint adouble:

AbstractIntDoubleMap map = new OpenIntDoubleHashMap();

Então, podemos adicionar valor:

map.put(1, 4.5);

E recupere-o:

double value = map.get(1);

Além disso, os mapas primitivos Colt fornecem métodos padrão comocontainsKey(value), containsValue(key),ekeyOf(value).

4.2. Endereçamento aberto vs encadeamento

The cern.colt.map package contains automatically growing and shrinking maps for double and int primitive data types. Sob o capô, eles usam endereçamento aberto com hash duplo. O endereçamento aberto significa que todas as entradas são armazenadas na tabela de hashwithout using additional data structures.

Java, on the other hand, uses chaining. Isso é bom para resolver colisões, mas requer mais espaço de memória devido ao fato de exigir váriosLinkedLists.

Para associações de double aint, o equivalenteHashMap do Java principal éOpenDoubleIntHashMap. Da mesma forma, OpenIntDoubleHashMap é paraint adouble, eOpenIntIntHashMap paraint aint. E, finalmente, a classeOpenLongObjectHashMap é para os tiposlong aObject.

Além disso, cada implementação de mapa tem uma classe base abstrata comoAbstractDoubleIntMap, AbstractIntDoubleMap, AbstractIntIntMap,eAbstractLongObjectMap.

5. Fastutil

Fastutil is a fast and compact framework which provides type-specific collections including primitive type maps.

5.1. Exemplo rápido

Assim como o Eclipse Collections and Trove, o Fastutil também fornece mapas de associação primitivos a primitivos e primitivos para tipos de objetos.

Vamos criar a instância do mapa primitivo deint aboolean:

Int2BooleanMap int2BooleanMap = new Int2BooleanOpenHashMap();

Além disso, vamos adicionar algumas entradas nele:

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

Além disso, podemos recuperar alguns dos valores por sua chave:

boolean value = int2BooleanMap.get(1);

Finalmente, aqui está como criamos um mapa vazio deint classificado paraboolean:

Int2BooleanSortedMap int2BooleanSorted = Int2BooleanSortedMaps.EMPTY_MAP;

5.2. Mapas primitivos

Vamos escolher a associação de valor-chaveint aboolean como exemplo. O pacoteit.unimi.dsi.fastutil.ints contém uma variedade de interfaces comoInt2BooleanMapeInt2BooleanSortedMap.

Curiosamente, também temosInt2BooleanOpenHashMap para endereçamento aberto, como o Colt.

Além disso,we can create maps with a custom hashing strategy withInt2BooleanOpenCustomHashMap. Isso é bom, pois os primitivos não podem estenderequals andhashCode por conta própria.

6. Conclusão

Neste artigo, aprendemos comocreate primitive maps in Java using Eclipse Collections, Trove, Colt, andFastutil.

Finalmente, o código completo para este artigo está disponívelover on GitHub.