Lembre-se de que um Mapa são dados estruturados que consistem em um conjunto de pares de valores-chave, e cada chave só pode ser usada uma vez em um único Mapa. Este tópico aborda 9 questões básicas sobre o uso do Map em Java e suas classes implementadas. Para simplificar, usarei generalizações nos exemplos . Portanto, escreverei simplesmente Map, sem especificar o especificador Map. Mas você pode assumir que ambos os valores de K e V são comparáveis, o que significa que K estende Comparable e V também estende Comparable .
0. Convertendo um mapa em uma lista
Em Java, a interface Map oferece três tipos de coleções: um conjunto de chaves, um conjunto de valores e um conjunto de valores-chave. Todos eles podem ser transformados em uma Lista usando o construtor ou métodoaddAll()
. O trecho de código a seguir demonstra como criar um ArrayList a partir de um mapa.
// list of keys
List keyList = new ArrayList(Map.keySet());
//list of values
List valueList = new ArrayList(Map.valueSet());
//list key-value
List entryList = new ArrayList(Map.entrySet());
1. Percorra todos os valores do mapa
Percorrer cada par de valores-chave é o procedimento mais básico para percorrer um mapa. Em Java, cada par é armazenado em um campo Map chamado Map.Entry .Map.entrySet()
retorna um conjunto de valores-chave, então a maneira mais eficiente de iterar todos os valores de um Mapa seria:
for(Entry entry: Map.entrySet()) {
//get the key
K key = entry.getKey();
//get value
V value = entry.getValue();
}
Também podemos usar Iterator
, especialmente em versões anteriores ao JDK 1.5
Iterator itr = Map.entrySet().iterator();
while(itr.hasNext()) {
Entry entry = itr.next();
//get the key
K key = entry.getKey();
//get value
V value = entry.getValue();
}
2. Ordenação do mapa por chaves
Organizar mapas por chaves é outro procedimento comumente utilizado. A primeira maneira é adicionar Map.Entry à lista e classificar usando um comparador que classifica por valores.List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {
@Override
public int compare(Entry e1, Entry e2) {
return e1.getKey().compareTo(e2.getKey());
}
});
Outra forma: use SortedMap , que, além disso, também organiza suas chaves em ordem. Porém, todas as chaves devem incorporar Comparável ou ser aceitas pelo comparador. Uma das classes implementadas SortedMap
é TreeMap . Seu construtor aceita um comparador. O código a seguir mostra como transformar um normal Map
em um ordenado.
SortedMap sortedMap = new TreeMap(new Comparator() {
@Override
public int compare(K k1, K k2) {
return k1.compareTo(k2);
}
});
sortedMap.putAll(Map);
3. Ordenar mapa por valores
Adicionar um mapa à lista e depois classificá-lo funciona neste caso, mas desta vez você precisa usarEntry.getValue()
. O código abaixo é quase o mesmo de antes.
List list = new ArrayList(Map.entrySet());
Collections.sort(list, new Comparator() {
@Override
public int compare(Entry e1, Entry e2) {
return e1.getValue().compareTo(e2.getValue());
}
});
Ainda podemos usá-lo SortedMap
neste caso, mas apenas se os valores forem únicos. Nesse caso, você pode transformar o par de valores-chave em um valor-chave. Esta solução tem limitações severas e não é recomendada por mim.
4. Inicializando um mapa estático/imutável
Quando você deseja que um Mapa permaneça imutável, uma boa maneira é copiá-lo para um Mapa imutável. Esta técnica de programação defensiva o ajudará a criar um mapa que não seja apenas seguro de usar, mas também seguro para threads. Para inicializar um mapa estático/imutável, podemos usar um inicializadorstatic
(veja abaixo). O problema desse código é que apesar de declarar um Map como static final
, ainda podemos trabalhar com ele após a inicialização, por exemplo Test.Map.put(3,"three");
. Portanto, não é uma imutabilidade real. Para criar um mapa imutável usando um inicializador estático, precisamos de uma classe superanônima, que adicionaremos ao mapa imutável na última etapa de inicialização. Por favor, olhe a segunda parte do código. Quando uma UnsupportedOperationException será lançada se você executar o Test.Map.put(3,"three");
.
public class Test {
private static final Map Map;
static {
Map = new HashMap();
Map.put(1, "one");
Map.put(2, "two");
}
}
public class Test {
private static final Map Map;
static {
Map aMap = new HashMap();
aMap.put(1, "one");
aMap.put(2, "two");
Map = Collections.unmodifiableMap(aMap);
}
}
A biblioteca Guava também oferece suporte a várias maneiras de inicializar coleções estáticas e imutáveis. Para saber mais sobre os benefícios do utilitário de coleções imutáveis do Guava, consulte a seção Coleções imutáveis no Guia do Guava .
5. Diferença entre HashMap, TreeMap e Hashtable
Existem três implementações principais da interface Map em Java: HashMap , TreeMap e Hashtable . As principais diferenças são as seguintes:- Ordem de passagem . HashMap e HashTable não garantem a ordem do Mapa; em particular, não garantem que a ordem permanecerá a mesma ao longo do tempo. Mas
TreeMap
irá ordenar todos os valores na “ordem natural” das chaves ou por um comparador. - Pares de valores-chave válidos.
HashMap
permite que você tenha uma chave nula e um valor nulo.HashTable
não permite uma chave nula ou um valor nulo. SeTreeMap
a ordem natural for usada ou o comparador não permitir uma chave nula, uma exceção será lançada. - Sincronização . Apenas
HashTable
sincronizado, o resto não. Mas, "se uma implementação thread-safe não for necessária, é recomendado usar "HashMap
em vez dissoHashTable
.
. | HashMap | HashTable | TreeMap
-------------------------------------------------------
Упорядочивание |нет |нет | да
null в ключ-meaning | да-да | нет-нет | нет-да
синхронизировано | нет | да | нет
производительность | O(1) | O(1) | O(log n)
воплощение | корзины | корзины | красно-чёрное дерево
Leia mais sobre o relacionamento HashMap vs. TreeMap vs. Tabela hash vs. LinkedHashMap .
6. Mapa com pesquisa/visualização reversa
Às vezes, precisamos de um conjunto de pares chave-chave, o que significa que os valores são tão exclusivos quanto as chaves (um padrão um para um). Esta consistência permite criar uma "visão/pesquisa invertida" no Mapa. Ou seja, podemos encontrar uma chave pelo seu valor. Essa estrutura de dados é chamada de Map bidirecional , que infelizmente não é suportada pelo JDK. Tanto o Apache Common Collections quanto o Guava oferecem implementações de mapas bidirecionais chamadas BidiMap e BiMap, respectivamente. Ambos introduzem uma restrição que impõe um mapeamento 1:1 entre chaves e valores.7. Cópia superficial do mapa
Quase todos, senão todos, Mapas em Java contêm um construtor de cópia para outro Mapa. Mas o procedimento de cópia não está sincronizado. O que significa que quando um thread copia um mapa, outro thread pode alterar sua estrutura. Para evitar a dessincronização repentina da cópia, um deles deve ser usado nesse casoCollections.synchronizedMap()
.
Map copiedMap = Collections.synchronizedMap(Map);
Outra maneira interessante de copiar superficialmente é usar o arquivo clone()
. Mas NÃO é recomendado nem mesmo pelo criador do framework de coleções Java, Joshua Bloch. No debate " Construtor de cópia vs. clonagem ", ele assume a posição: Citação: "Muitas vezes incluo um método de clone público em classes concretas porque as pessoas esperam que eles estejam lá. ... é uma pena que a clonagem esteja quebrada, mas é aconteceu... A clonagem é um ponto fraco e acho que as pessoas deveriam ser alertadas sobre suas limitações." Por esse motivo, nem mostro como usar o método clone()
para copiar Map
8. Crie um mapa vazio
SeMap
imutável, use:
Map = Collections.emptyMap();
Ou use qualquer outra modalidade. Por exemplo:
Map = new HashMap();
FIM
GO TO FULL VERSION