Java HashMap é uma das classes de Coleção mais populares em Java. Java HashMap é uma implementação baseada em tabela hash. HashMap em Java estende a classe AbstractMap que implementa a interface Map.
Java HashMap
Alguns pontos importantes sobre HashMap em Java são;
- Java HashMap permite chave nula e valores nulos.
- HashMap não é uma coleção ordenada. Você pode iterar sobre as entradas do HashMap através do conjunto de chaves, mas não é garantido que estejam na ordem em que foram adicionadas ao HashMap.
- HashMap é quase semelhante a Hashtable, exceto que é não sincronizado e permite chave e valores nulos.
- HashMap usa sua classe interna Node<K,V> para armazenar as entradas do mapa.
- HashMap armazena entradas em várias listas encadeadas simples, chamadas de buckets ou bins. O número padrão de bins é 16 e é sempre uma potência de 2.
- HashMap usa os métodos hashCode() e equals() nas chaves para operações de get e put. Portanto, o objeto chave do HashMap deve fornecer uma boa implementação desses métodos. Esta é a razão pela qual classes imutáveis são mais adequadas para chaves, por exemplo, String e Integer.
- Java HashMap não é seguro para threads, para ambientes multithread, você deve usar a classe ConcurrentHashMap ou obter um mapa sincronizado usando o método
Collections.synchronizedMap()
.
Construtores do Java HashMap
O Java HashMap fornece quatro construtores.
- public HashMap(): O construtor HashMap mais comumente usado. Este construtor irá criar um HashMap vazio com capacidade inicial padrão de 16 e fator de carga 0.75
- public HashMap(int initialCapacity): Este construtor HashMap é usado para especificar a capacidade inicial e o fator de carga 0.75. Isso é útil para evitar o rehashing se você souber o número de mapeamentos a serem armazenados no HashMap.
- public HashMap(int initialCapacity, float loadFactor): Este construtor HashMap criará um HashMap vazio com capacidade e fator de carga especificados. Você pode usar isso se souber o número máximo de mapeamentos a serem armazenados no HashMap. Em cenários comuns, você deve evitar isso porque o fator de carga 0.75 oferece um bom equilíbrio entre custo de espaço e tempo.
- public HashMap(Map<? extends K, ? extends V> m): Cria um Map com os mesmos mapeamentos do mapa especificado e com fator de carga 0.75
Exemplo de Construtores do Java HashMap
O trecho de código abaixo mostra um exemplo de HashMap usando todos os construtores acima.
Map<String, String> map1 = new HashMap<>();
Map<String, String> map2 = new HashMap<>(2^5);
Map<String, String> map3 = new HashMap<>(32,0.80f);
Map<String,String> map4 = new HashMap<>(map1);
Métodos HashMap do Java
Vamos dar uma olhada nos métodos importantes do HashMap em Java.
- public void clear(): Este método HashMap removerá todos os mapeamentos e o HashMap ficará vazio.
- public boolean containsKey(Object key): Este método retorna ‘true’ se a chave existir, caso contrário, retornará ‘false’.
- public boolean containsValue(Object value): Este método HashMap retorna true se o valor existir, caso contrário, retorna false.
- public Set<Map.Entry<K,V>> entrySet(): Este método retorna uma visão de conjunto dos mapeamentos do HashMap. Este conjunto é suportado pelo mapa, portanto, alterações no mapa são refletidas no conjunto, e vice-versa.
- public V get(Object key): Retorna o valor mapeado para a chave especificada, ou null se não houver mapeamento para a chave.
- public boolean isEmpty(): Um método de utilidade que retorna true se não houver mapeamentos chave-valor presentes.
- public Set<K> keySet(): Retorna uma visão de conjunto das chaves contidas neste mapa. O conjunto é suportado pelo mapa, então, alterações no mapa são refletidas no conjunto, e vice-versa.
- public V put(K key, V value): Associa o valor especificado à chave especificada neste mapa. Se o mapa anteriormente continha um mapeamento para a chave, o valor antigo é substituído.
- public void putAll(Map<? extends K, ? extends V> m): Copia todas as associações do mapa especificado para este mapa. Essas associações substituirão quaisquer associações que este mapa tenha para quaisquer chaves atualmente no mapa especificado.
- public V remove(Object key): Remove a associação da chave especificada deste mapa, se presente.
- public int size(): Retorna o número de associações chave-valor neste mapa.
- public Collection<V> values(): Retorna uma visão de coleção dos valores contidos neste mapa. A coleção é suportada pelo mapa, então as alterações no mapa são refletidas na coleção, e vice-versa.
Há muitos novos métodos em HashMap introduzidos no Java 8.
- public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction): Se a chave especificada ainda não estiver associada a um valor (ou estiver mapeada para null), este método tenta calcular seu valor usando a função de mapeamento fornecida e o insere no HashMap, a menos que seja Null.
- public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): Se o valor para a chave especificada estiver presente e não for nulo, tenta calcular uma nova associação dada a chave e seu valor atual mapeado.
- public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction): Este método HashMap tenta calcular uma associação para a chave especificada e seu valor atual mapeado.
- public void forEach(BiConsumer<? super K, ? super V> action): Este método executa a ação fornecida para cada entrada neste mapa.
- public V getOrDefault(Object key, V defaultValue): Semelhante a get, exceto que defaultValue é retornado se nenhuma correspondência for encontrada para a chave especificada.
- public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction): Se a chave especificada ainda não estiver associada a um valor ou estiver associada a null, ela é associada ao valor não nulo fornecido. Caso contrário, substitui o valor associado pelos resultados da função de remapeamento fornecida, ou remove se o resultado for null.
- public V putIfAbsent(K key, V value): Se a chave especificada ainda não estiver associada a um valor (ou estiver mapeada para null), ela é associada ao valor fornecido e retorna null; caso contrário, retorna o valor atual.
- public boolean remove(Object key, Object value): Remove a entrada para a chave especificada apenas se ela estiver atualmente mapeada para o valor especificado.
- public boolean replace(K key, V oldValue, V newValue): Substitui a entrada para a chave especificada apenas se estiver atualmente mapeada para o valor especificado.
- public V replace(K key, V value): Substitui a entrada para a chave especificada apenas se ela estiver atualmente mapeada para algum valor.
- public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function): Substitui o valor de cada entrada pelo resultado da invocação da função fornecida nessa entrada.
Exemplo de Java HashMap
Aqui está um programa Java simples para os métodos comumente usados em HashMap.
package com.journaldev.examples;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class HashMapExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "1"); // put example
map.put("2", "2");
map.put("3", "3");
map.put("4", null); // null value
map.put(null, "100"); // null key
String value = map.get("3"); // get example
System.out.println("Key = 3, Value = " + value);
value = map.getOrDefault("5", "Default Value");
System.out.println("Key = 5, Value=" + value);
boolean keyExists = map.containsKey(null);
boolean valueExists = map.containsValue("100");
System.out.println("keyExists=" + keyExists + ", valueExists=" + valueExists);
Set<Entry<String, String>> entrySet = map.entrySet();
System.out.println(entrySet);
System.out.println("map size=" + map.size());
Map<String, String> map1 = new HashMap<>();
map1.putAll(map);
System.out.println("map1 mappings= " + map1);
String nullKeyValue = map1.remove(null);
System.out.println("map1 null key value = " + nullKeyValue);
System.out.println("map1 after removing null key = " + map1);
Set<String> keySet = map.keySet();
System.out.println("map keys = " + keySet);
Collection<String> values = map.values();
System.out.println("map values = " + values);
map.clear();
System.out.println("map is empty=" + map.isEmpty());
}
}
A seguir está a saída do exemplo de programa Java HashMap acima.
Key = 3, Value = 3
Key = 5, Value=Default Value
keyExists=true, valueExists=true
[null=100, 1=1, 2=2, 3=3, 4=null]
map size=5
map1 mappings= {null=100, 1=1, 2=2, 3=3, 4=null}
map1 null key value = 100
map1 after removing null key = {1=1, 2=2, 3=3, 4=null}
map keys = [null, 1, 2, 3, 4]
map values = [100, 1, 2, 3, null]
map is empty=true
Como o HashMap funciona em Java?
HashMap em Java usa sua classe interna Node<K,V> para armazenar mapeamentos. HashMap funciona com um algoritmo de hash e usa os métodos hashCode() e equals() na chave para operações de obtenção e colocação. HashMap usa uma lista ligada simples para armazenar elementos, estes são chamados de bins ou buckets. Quando chamamos o método put, o hashCode da chave é usado para determinar o bucket que será usado para armazenar o mapeamento. Uma vez que o bucket é identificado, o hashCode é usado para verificar se já existe uma chave com o mesmo hashCode ou não. Se houver uma chave existente com o mesmo hashCode, então o método equals() é usado na chave. Se equals retornar true, então o valor é sobrescrito, caso contrário, é feito um novo mapeamento para este bucket de lista ligada simples. Se não houver chave com o mesmo hashCode, então o mapeamento é inserido no bucket. Para a operação get do HashMap, novamente o hashCode da chave é usado para determinar o bucket para procurar o valor. Depois que o bucket é identificado, as entradas são percorridas para descobrir a Entry usando o hashCode e o método equals. Se uma correspondência for encontrada, o valor é retornado, caso contrário, null é retornado. Existem muitas outras coisas envolvidas, como algoritmo de hash para obter o bucket para a chave, rehashing de mapeamentos etc. Mas para o nosso trabalho, apenas lembre-se de que as operações do HashMap funcionam na chave e uma boa implementação dos métodos hashCode e equals é necessária para evitar comportamentos indesejados. A imagem abaixo mostra a explicação das operações de obtenção e colocação. Leitura Recomendada: Importância dos métodos hashCode e equals em Java
Fator de Carga do HashMap Java
O fator de carga é usado para determinar quando o HashMap será rehashed e o tamanho do bucket será aumentado. O valor padrão do bucket ou capacidade é 16 e o fator de carga é 0,75. O limiar para o rehashing é calculado multiplicando a capacidade e o fator de carga. Assim, o valor padrão do limiar será 12. Portanto, quando o HashMap tiver mais de 12 mapeamentos, ele será rehashed e o número de bins será aumentado para o próximo de potência 2, ou seja, 32. Note que a capacidade do HashMap é sempre uma potência de 2. O fator de carga padrão de 0,75 fornece um bom equilíbrio entre espaço e complexidade de tempo. Mas você pode defini-lo para valores diferentes com base em seus requisitos. Se você quiser economizar espaço, pode aumentar o valor para 0,80 ou 0,90, mas as operações de obtenção/inserção levarão mais tempo.
Java HashMap keySet
O método keySet do Java HashMap retorna a visualização Set das chaves no HashMap. Esta visualização Set é apoiada pelo HashMap e quaisquer alterações no HashMap são refletidas no Set e vice-versa. Abaixo está um programa simples demonstrando exemplos de keySet do HashMap e qual é o caminho a seguir se você quiser um keySet não apoiado pelo mapa.
package com.journaldev.examples;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
public class HashMapKeySetExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put("3", "3");
Set<String> keySet = map.keySet();
System.out.println(keySet);
map.put("4", "4");
System.out.println(keySet); // keySet is backed by Map
keySet.remove("1");
System.out.println(map); // map is also modified
keySet = new HashSet<>(map.keySet()); // copies the key to new Set
map.put("5", "5");
System.out.println(keySet); // keySet is not modified
}
}
A saída do programa acima deixará claro que o keySet é apoiado pelo mapa.
[1, 2, 3]
[1, 2, 3, 4]
{2=2, 3=3, 4=4}
[2, 3, 4]
Valores do HashMap em Java
O método de valores do HashMap em Java retorna uma visualização de coleção dos valores no Mapa. Esta coleção é suportada pelo HashMap, então quaisquer mudanças no HashMap serão refletidas na coleção de valores e vice-versa. Um exemplo simples abaixo confirma esse comportamento da coleção de valores do HashMap.
package com.journaldev.examples;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class HashMapValuesExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put("3", null);
map.put("4", null);
map.put(null, "100");
Collection<String> values = map.values();
System.out.println("map values = " + values);
map.remove(null);
System.out.println("map values after removing null key = " + values);
map.put("5", "5");
System.out.println("map values after put = " + values);
System.out.println(map);
values.remove("1"); // changing values collection
System.out.println(map); // updates in map too
}
}
A saída do programa acima é a seguinte:
map values = [100, 1, 2, null, null]
map values after removing null key = [1, 2, null, null]
map values after put = [1, 2, null, null, 5]
{1=1, 2=2, 3=null, 4=null, 5=5}
{2=2, 3=null, 4=null, 5=5}
Conjunto de entradas do HashMap em Java
O método entrySet do HashMap em Java retorna a visualização de conjunto de mapeamentos. Este entrySet é suportado pelo HashMap, então quaisquer mudanças no mapa são refletidas no conjunto de entradas e vice-versa. Dê uma olhada no programa de exemplo abaixo para um exemplo de entrySet do HashMap.
package com.journaldev.examples;
import java.util.AbstractMap;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class HashMapEntrySetExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", null);
map.put(null, "100");
Set<Entry<String,String>> entrySet = map.entrySet();
Iterator<Entry<String, String>> iterator = entrySet.iterator();
Entry<String, String> next = null;
System.out.println("map before processing = "+map);
System.out.println("entrySet before processing = "+entrySet);
while(iterator.hasNext()){
next = iterator.next();
System.out.println("Processing on: "+next.getValue());
if(next.getKey() == null) iterator.remove();
}
System.out.println("map after processing = "+map);
System.out.println("entrySet after processing = "+entrySet);
Entry<String, String> simpleEntry = new AbstractMap.SimpleEntry<String, String>("1","1");
entrySet.remove(simpleEntry);
System.out.println("map after removing Entry = "+map);
System.out.println("entrySet after removing Entry = "+entrySet);
}
}
Abaixo está a saída produzida pelo programa acima:
map before processing = {null=100, 1=1, 2=null}
entrySet before processing = [null=100, 1=1, 2=null]
Processing on: 100
Processing on: 1
Processing on: null
map after processing = {1=1, 2=null}
entrySet after processing = [1=1, 2=null]
map after removing Entry = {2=null}
entrySet after removing Entry = [2=null]
Método putIfAbsent do HashMap em Java
A simple example for HashMap putIfAbsent method introduced in Java 8.
package com.journaldev.examples;
import java.util.HashMap;
import java.util.Map;
public class HashMapPutIfAbsentExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", null);
map.put(null, "100");
System.out.println("map before putIfAbsent = "+map);
String value = map.putIfAbsent("1", "4");
System.out.println("map after putIfAbsent = "+map);
System.out.println("putIfAbsent returns: "+value);
System.out.println("map before putIfAbsent = "+map);
value = map.putIfAbsent("3", "3");
System.out.println("map after putIfAbsent = "+map);
System.out.println("putIfAbsent returns: "+value);
}
}
A saída do programa acima é a seguinte:
map before putIfAbsent = {null=100, 1=1, 2=null}
map after putIfAbsent = {null=100, 1=1, 2=null}
putIfAbsent returns: 1
map before putIfAbsent = {null=100, 1=1, 2=null}
map after putIfAbsent = {null=100, 1=1, 2=null, 3=3}
putIfAbsent returns: null
Método forEach do HashMap em Java
O método forEach do HashMap foi introduzido no Java 8. É um método muito útil para executar a ação fornecida para cada entrada no mapa até que todas as entradas tenham sido processadas ou a ação lance uma exceção.
package com.journaldev.examples;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiConsumer;
public class HashMapForEachExample {
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("1", "1");
map.put("2", null);
map.put(null, "100");
BiConsumer action = new MyBiConsumer();
map.forEach(action);
//exemplo de expressão lambda
System.out.println("\nHashMap forEach lambda example\n");
map.forEach((k,v) -> {System.out.println("Key = "+k+", Value = "+v);});
}
}
class MyBiConsumer implements BiConsumer {
@Override
public void accept(String t, String u) {
System.out.println("Key = " + t);
System.out.println("Processing on value = " + u);
}
}
A saída do programa de exemplo do forEach do HashMap acima é;
Key = null
Processing on value = 100
Key = 1
Processing on value = 1
Key = 2
Processing on value = null
HashMap forEach lambda example
Key = null, Value = 100
Key = 1, Value = 1
Key = 2, Value = null
Java HashMap replaceAll
O método replaceAll do HashMap pode ser usado para substituir o valor de cada entrada pelo resultado da invocação da função fornecida para essa entrada. Este método foi adicionado no Java 8 e podemos usar expressões lambda como argumento para este método.
package com.journaldev.examples;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
public class HashMapReplaceAllExample {
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put(null, "100");
System.out.println("map before replaceAll = " + map);
BiFunction function = new MyBiFunction();
map.replaceAll(function);
System.out.println("map after replaceAll = " + map);
// replaceAll usando expressões lambda
map.replaceAll((k, v) -> {
if (k != null) return k + v;
else return v;});
System.out.println("map after replaceAll lambda expression = " + map);
}
}
class MyBiFunction implements BiFunction {
@Override
public String apply(String t, String u) {
if (t != null)
return t + u;
else
return u;
}
}
A saída do programa replaceAll do HashMap acima é;
map before replaceAll = {null=100, 1=1, 2=2}
map after replaceAll = {null=100, 1=11, 2=22}
map after replaceAll lambda example = {null=100, 1=111, 2=222}
Java HashMap computeIfAbsent
O método computeIfAbsent do HashMap calcula o valor apenas se a chave não estiver presente no mapa. Após calcular o valor, ele é inserido no mapa se não for nulo.
package com.journaldev.examples;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
public class HashMapComputeIfAbsent {
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("1", "10");
map.put("2", "20");
map.put(null, "100");
Function function = new MyFunction();
map.computeIfAbsent("3", function); //key not present
map.computeIfAbsent("2", function); //key already present
//modo lambda
map.computeIfAbsent("4", v -> {return v;});
map.computeIfAbsent("5", v -> {return null;}); //null value won't get inserted
System.out.println(map);
}
}
class MyFunction implements Function {
@Override
public String apply(String t) {
return t;
}
}
A saída do programa acima é;
{null=100, 1=10, 2=20, 3=3, 4=4}
Java HashMap computeIfPresent
O método computeIfPresent do Java HashMap recalcula o valor se a chave especificada estiver presente e o valor não for nulo. Se a função retornar nulo, o mapeamento é removido.
package com.journaldev.examples;
import java.util.HashMap;
import java.util.Map;
import java.util.function.BiFunction;
public class HashMapComputeIfPresentExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "10");
map.put("2", "20");
map.put(null, "100");
map.put("10", null);
System.out.println("map before computeIfPresent = " + map);
BiFunction<String, String, String> function = new MyBiFunction1();
for (String key : map.keySet()) {
map.computeIfPresent(key, function);
}
System.out.println("map after computeIfPresent = " + map);
map.computeIfPresent("1", (k,v) -> {return null;}); // mapping will be removed
System.out.println("map after computeIfPresent = " + map);
}
}
class MyBiFunction1 implements BiFunction<String, String, String> {
@Override
public String apply(String t, String u) {
return t + u;
}
}
A saída produzida pelo exemplo de uso do computeIfPresent do HashMap é;
map before computeIfPresent = {null=100, 1=10, 2=20, 10=null}
map after computeIfPresent = {null=null100, 1=110, 2=220, 10=null}
map after computeIfPresent = {null=null100, 2=220, 10=null}
Java HashMap compute
Se você deseja aplicar uma função a todos os mapeamentos com base em sua chave e valor, o método compute deve ser usado. Se não houver mapeamento e este método for usado, o valor será nulo para a função compute.
package com.journaldev.examples;
import java.util.HashMap;
import java.util.Map;
public class HashMapComputeExample {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put(null, "10");
map.put("10", null);
System.out.println("map before compute = "+map);
for (String key : map.keySet()) {
map.compute(key, (k,v) -> {return k+v;});
}
map.compute("5", (k,v) -> {return k+v;}); //key not present, v = null
System.out.println("map after compute = "+map);
}
}
A saída do exemplo de uso do compute do HashMap é;
map before compute = {null=10, 1=1, 2=2, 10=null}
map after compute = {null=null10, 1=11, 2=22, 5=5null, 10=10null}
Java HashMap merge
Se a chave especificada não estiver presente ou estiver associada a nulo, ela será associada ao valor não nulo fornecido. Caso contrário, substitui o valor associado pelos resultados da função de remapeamento fornecida ou remove se o resultado for nulo.
package com.journaldev.examples;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
public class HashMapMergeExample {
public static void main(String[] args) {
Map map = new HashMap<>();
map.put("1", "1");
map.put("2", "2");
map.put(null, "10");
map.put("10", null);
for (Entry entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
//merge lança NullPointerException se a chave ou o valor for nulo
if(key != null && value != null)
map.merge(entry.getKey(), entry.getValue(),
(k, v) -> {return k + v;});
}
System.out.println(map);
map.merge("5", "5", (k, v) -> {return k + v;}); // key not present
System.out.println(map);
map.merge("1", "1", (k, v) -> {return null;}); // method return null, so remove
System.out.println(map);
}
}
A saída do programa acima é;
{null=10, 1=11, 2=22, 10=null}
{null=10, 1=11, 2=22, 5=5, 10=null}
{null=10, 2=22, 5=5, 10=null}
Isso éIsso é tudo para HashMap em Java, espero que nada importante ten tudoha sobre sido HashMap em Java, perd espero queido. nada importante Com tenparthailhe sido deix tambémado com de fora outros. se você Com gostpartouilhe. também Refer comência outras: pessoas Document se vocêação da gost APIou.. Referência: Documentação da API
Source:
https://www.digitalocean.com/community/tutorials/java-hashmap