HashMap em Java com exemplos
HashMap <K, V> é uma parte da coleção Java desde Java 1.2. Esta classe é encontrada no pacote java.util . Ele fornece a implementação básica da interface Map do Java. Ele armazena os dados em pares (chave, valor) e você pode acessá-los por um índice de outro tipo (por exemplo, um inteiro). Um objeto é usado como uma chave (índice) para outro objeto (valor). Se você tentar inserir a chave duplicada, ela substituirá o elemento da chave correspondente.
HashMap é semelhante a HashTable , mas não está sincronizado. Ele permite armazenar as chaves nulas também, mas deve haver apenas um objeto de chave nula e pode haver qualquer número de valores nulos. Esta classe não oferece garantias quanto à ordem do mapa. Para usar essa classe e seus métodos, você precisa importar o pacote java.util.HashMap ou sua superclasse.
// Java program to illustrate HashMap class of java.util
// package
// Importing HashMap class
import java.util.HashMap;
// Main class
public class GFG {
// Main driver method
public static void main(String[] args)
{
// Create an empty hash map by declaring object
// of string and integer type
HashMap<String, Integer> map = new HashMap<>();
// Adding elements to the Map
// using standard add() method
map.put("vishal", 10);
map.put("sachin", 30);
map.put("vaibhav", 20);
// Print size and content of the Map
System.out.println("Size of map is:- "
+ map.size());
// Printing elements in object of Map
System.out.println(map);
// Checking if a key is present and if
// present, print value by passing
// random element
if (map.containsKey("vishal")) {
// Mapping
Integer a = map.get("vishal");
// Printing value fr the corresponding key
System.out.println("value for key"
+ " \"vishal\" is:- " + a);
}
}
}
O tamanho do mapa é: - 3 {vaibhav = 20, vishal = 10, sachin = 30} o valor da chave "vishal" é: - 10
A hierarquia do HashMap é a seguinte:
Sintaxe: Declaração
public class HashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Cloneable, Serializable
Parâmetros: leva dois parâmetros, a saber:
- O tipo de chaves mantidas por este mapa
- O tipo de valores mapeados
HashMap implementa interfaces Serializable , Cloneable , Map <K, V> . HashMap estende a classe AbstractMap <K, V> . As subclasses diretas são LinkedHashMap , PrinterStateReasons .
Os construtores no HashMap são os seguintes:
O HashMap fornece 4 construtores e o modificador de acesso de cada um é público, os quais são listados a seguir:
- HashMap()
- HashMap (int initialCapacity)
- HashMap (int initialCapacity, float loadFactor)
- HashMap (mapa do mapa)
Agora, discutindo os construtores acima, um por um, juntamente com a implementação dos mesmos com a ajuda de programas Java limpos.
Construtor 1: HashMap()
É o construtor padrão que cria uma instância de HashMap com uma capacidade inicial de 16 e fator de carga de 0,75.
Sintaxe:
HashMap<K, V> hm = new HashMap<K, V>();
Exemplo
// Java program to Demonstrate the HashMap() constructor
// Importing bsiic required classes
import java.io.*;
import java.util.*;
// Main class
// To add elements to HashMap
class GFG {
// Main driver method
public static void main(String args[])
{
// No need to mention the
// Generic type twice
HashMap<Integer, String> hm1 = new HashMap<>();
// Initialization of a HashMap using Generics
HashMap<Integer, String> hm2
= new HashMap<Integer, String>();
// Adding elements using put method
// Custom input elements
hm1.put(1, "one");
hm1.put(2, "two");
hm1.put(3, "three");
hm2.put(4, "four");
hm2.put(5, "five");
hm2.put(6, "six");
// Print and display mapping of HashMap 1
System.out.println("Mappings of HashMap hm1 are : "
+ hm1);
// Print and display mapping of HashMap 2
System.out.println("Mapping of HashMap hm2 are : "
+ hm2);
}
}
Os mapeamentos de HashMap hm1 são: {1 = um, 2 = dois, 3 = três} Mapeamento de HashMap hm2 são: {4 = quatro, 5 = cinco, 6 = seis}
Construtor 2: HashMap (int initialCapacity)
Ele cria uma instância de HashMap com uma capacidade inicial especificada e fator de carga de 0,75.
Sintaxe:
HashMap<K, V> hm = new HashMap<K, V>(int initialCapacity);
Exemplo
// Java program to Demonstrate
// HashMap(int initialCapacity) Constructor
// Importing basic classes
import java.io.*;
import java.util.*;
// Main class
// To add elements to HashMap
class AddElementsToHashMap {
// Main driver method
public static void main(String args[])
{
// No need to mention the
// Generic type twice
HashMap<Integer, String> hm1 = new HashMap<>(10);
// Initialization of a HashMap using Generics
HashMap<Integer, String> hm2
= new HashMap<Integer, String>(2);
// Adding elements to object of HashMap
// using put method
// HashMap 1
hm1.put(1, "one");
hm1.put(2, "two");
hm1.put(3, "three");
// HashMap 2
hm2.put(4, "four");
hm2.put(5, "five");
hm2.put(6, "six");
// Printing elements of ahshMap 1
System.out.println("Mappings of HashMap hm1 are : "
+ hm1);
// Printing elements of HashMap 2
System.out.println("Mapping of HashMap hm2 are : "
+ hm2);
}
}
Os mapeamentos de HashMap hm1 são: {1 = um, 2 = dois, 3 = três} Mapeamento de HashMap hm2 são: {4 = quatro, 5 = cinco, 6 = seis}
Construtor 3: HashMap (int initialCapacity, float loadFactor)
Ele cria uma instância de HashMap com uma capacidade inicial especificada e um fator de carga especificado.
Sintaxe:
HashMap<K, V> hm = new HashMap<K, V>(int initialCapacity, int loadFactor);
Exemplo
// Java program to Demonstrate
// HashMap(int initialCapacity,float loadFactor) Constructor
// Importing basic classes
import java.io.*;
import java.util.*;
// Main class
// To add elements to HashMap
class GFG {
// Main driver method
public static void main(String args[])
{
// No need to mention the generic type twice
HashMap<Integer, String> hm1
= new HashMap<>(5, 0.75f);
// Initialization of a HashMap using Generics
HashMap<Integer, String> hm2
= new HashMap<Integer, String>(3, 0.5f);
// Add Elements using put() method
// Custom input elements
hm1.put(1, "one");
hm1.put(2, "two");
hm1.put(3, "three");
hm2.put(4, "four");
hm2.put(5, "five");
hm2.put(6, "six");
// Print and display elements in object of hashMap 1
System.out.println("Mappings of HashMap hm1 are : "
+ hm1);
// Print and display elements in object of hashMap 1
System.out.println("Mapping of HashMap hm2 are : "
+ hm2);
}
}
Os mapeamentos de HashMap hm1 são: {1 = um, 2 = dois, 3 = três} Mapeamento de HashMap hm2 são: {4 = quatro, 5 = cinco, 6 = seis}
4. HashMap (mapa do mapa): cria uma instância do HashMap com os mesmos mapeamentos do mapa especificado.
HashMap <K, V> hm = novo HashMap <K, V> (mapa do mapa);
// Java program to demonstrate the
// HashMap(Map map) Constructor
import java.io.*;
import java.util.*;
class AddElementsToHashMap {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
Map<Integer, String> hm1 = new HashMap<>();
// Add Elements using put method
hm1.put(1, "one");
hm1.put(2, "two");
hm1.put(3, "three");
// Initialization of a HashMap
// using Generics
HashMap<Integer, String> hm2
= new HashMap<Integer, String>(hm1);
System.out.println("Mappings of HashMap hm1 are : "
+ hm1);
System.out.println("Mapping of HashMap hm2 are : "
+ hm2);
}
}
Os mapeamentos de HashMap hm1 são: {1 = um, 2 = dois, 3 = três} Mapeamento de HashMap hm2 são: {1 = um, 2 = dois, 3 = três}
Executando várias operações no HashMap
1. Adicionando Elementos: Para adicionar um elemento ao mapa, podemos usar o método put() . No entanto, o pedido de inserção não é retido no Hashmap. Internamente, para cada elemento, um hash separado é gerado e os elementos são indexados com base nesse hash para torná-lo mais eficiente.
// Java program to add elements
// to the HashMap
import java.io.*;
import java.util.*;
class AddElementsToHashMap {
public static void main(String args[])
{
// No need to mention the
// Generic type twice
HashMap<Integer, String> hm1 = new HashMap<>();
// Initialization of a HashMap
// using Generics
HashMap<Integer, String> hm2
= new HashMap<Integer, String>();
// Add Elements using put method
hm1.put(1, "Geeks");
hm1.put(2, "For");
hm1.put(3, "Geeks");
hm2.put(1, "Geeks");
hm2.put(2, "For");
hm2.put(3, "Geeks");
System.out.println("Mappings of HashMap hm1 are : "
+ hm1);
System.out.println("Mapping of HashMap hm2 are : "
+ hm2);
}
}
Os mapeamentos de HashMap hm1 são: {1 = Geeks, 2 = For, 3 = Geeks} Mapeamento de HashMap hm2 são: {1 = Geeks, 2 = For, 3 = Geeks}
2. Mudando os Elementos: Depois de adicionar os elementos, se desejarmos mudar o elemento, isso pode ser feito adicionando novamente o elemento com o método put() . Uma vez que os elementos no mapa são indexados usando as chaves, o valor da chave pode ser alterado simplesmente inserindo o valor atualizado para a chave que desejamos alterar.
// Java program to change
// elements of HashMap
import java.io.*;
import java.util.*;
class ChangeElementsOfHashMap {
public static void main(String args[])
{
// Initialization of a HashMap
HashMap<Integer, String> hm
= new HashMap<Integer, String>();
// Change Value using put method
hm.put(1, "Geeks");
hm.put(2, "Geeks");
hm.put(3, "Geeks");
System.out.println("Initial Map " + hm);
hm.put(2, "For");
System.out.println("Updated Map " + hm);
}
}
Mapa inicial {1 = Geeks, 2 = Geeks, 3 = Geeks} Mapa atualizado {1 = Geeks, 2 = For, 3 = Geeks}
3. Removendo Elemento: Para remover um elemento do Mapa, podemos usar o método remove() . Este método pega o valor da chave e remove o mapeamento de uma chave deste mapa, se estiver presente no mapa.
// Java program to remove
// elements from HashMap
import java.io.*;
import java.util.*;
class RemoveElementsOfHashMap{
public static void main(String args[])
{
// Initialization of a HashMap
Map<Integer, String> hm
= new HashMap<Integer, String>();
// Add elements using put method
hm.put(1, "Geeks");
hm.put(2, "For");
hm.put(3, "Geeks");
hm.put(4, "For");
// Initial HashMap
System.out.println("Mappings of HashMap are : "
+ hm);
// remove element with a key
// using remove method
hm.remove(4);
// Final HashMap
System.out.println("Mappings after removal are : "
+ hm);
}
}
Os mapeamentos de HashMap são: {1 = Geeks, 2 = For, 3 = Geeks, 4 = For} Os mapeamentos após a remoção são: {1 = Geeks, 2 = For, 3 = Geeks}
4. Traversal de HashMap
Podemos usar a interface Iterator para percorrer qualquer estrutura do Collection Framework. Como os Iteradores trabalham com um tipo de dados, usamos Entry <? ,? > para resolver os dois tipos separados em um formato compatível. Então, usando o método next(), imprimimos as entradas de HashMap.
// Java program to traversal a
// Java.util.HashMap
import java.util.HashMap;
import java.util.Map;
public class TraversalTheHashMap {
public static void main(String[] args)
{
// initialize a HashMap
HashMap<String, Integer> map = new HashMap<>();
// Add elements using put method
map.put("vishal", 10);
map.put("sachin", 30);
map.put("vaibhav", 20);
// Iterate the map using
// for-each loop
for (Map.Entry<String, Integer> e : map.entrySet())
System.out.println("Key: " + e.getKey()
+ " Value: " + e.getValue());
}
}
Chave: valor vaibhav: 20 Chave: Vishal Valor: 10 Chave: valor sachin: 30
Recursos importantes do HashMap
Para acessar um valor, é preciso conhecer sua chave. HashMap é conhecido como HashMap porque usa uma técnica chamada Hashing. Hashing é uma técnica de converter uma string grande em uma string pequena que representa a mesma string. Um valor mais curto ajuda na indexação e pesquisas mais rápidas. O HashSet também usa o HashMap internamente.
Alguns recursos importantes do HashMap são:
- HashMap é uma parte do pacote java.util.
- HashMap estende uma classe abstrata AbstractMap que também fornece uma implementação incompleta da interface Map.
- Ele também implementa interfaces clonáveis e serializáveis . K e V na definição acima representam Chave e Valor, respectivamente.
- HashMap não permite chaves duplicadas, mas permite valores duplicados. Isso significa que uma única chave não pode conter mais de 1 valor, mas mais de 1 chave pode conter um único valor.
- O HashMap permite a chave nula também, mas apenas uma vez e vários valores nulos.
- Essa classe não oferece garantias quanto à ordem do mapa; em particular, não garante que o pedido permanecerá constante ao longo do tempo. É mais ou menos semelhante a HashTable, mas não está sincronizado.
Estrutura Interna do HashMap
Internamente, o HashMap contém uma matriz de Nó e um nó é representado como uma classe que contém 4 campos:
- hash int
- Tecla K
- Valor V
- Nó próximo
Pode-se observar que o nó contém uma referência ao seu próprio objeto. Portanto, é uma lista vinculada.
HashMap:
Nó:
Desempenho do HashMap
O desempenho do HashMap depende de 2 parâmetros que são nomeados da seguinte forma:
- Capacidade Inicial
- Fator de carga
1. Capacidade inicial - é a capacidade do HashMap no momento de sua criação (é o número de depósitos que um HashMap pode conter quando o HashMap é instanciado). Em java, é 2 ^ 4 = 16 inicialmente, o que significa que pode conter 16 pares de valores-chave.
2. Fator de carga - é o valor percentual da capacidade após o qual a capacidade do Hashmap deve ser aumentada (é a porcentagem de preenchimento dos depósitos após o qual ocorre o Rehashing). Em java, é 0.75f por padrão, o que significa que o novo hashing ocorre após preencher 75% da capacidade.
3. Limiar - É o produto do Fator de Carga e da Capacidade Inicial. Em java, por padrão, é (16 * 0,75 = 12). Ou seja, o Rehashing ocorre após a inserção de 12 pares de valores-chave no HashMap.
4. Rehashing - É o processo de dobrar a capacidade do HashMap após atingir seu Limiar. Em java, o HashMap continua a refazer o hash (por padrão) na seguinte sequência - 2 ^ 4, 2 ^ 5, 2 ^ 6, 2 ^ 7,…. em breve.
Se a capacidade inicial for mantida alta, o novo hashing nunca será feito. Mas, ao mantê-lo mais alto, aumenta a complexidade do tempo da iteração. Portanto, deve ser escolhido com muita habilidade para aumentar o desempenho. O número esperado de valores deve ser levado em consideração para definir a capacidade inicial. O valor do fator de carga mais geralmente preferido é 0,75, o que fornece uma boa relação entre os custos de tempo e espaço. O valor do fator de carga varia entre 0 e 1.
Nota: A partir do Java 8 em diante, o Java começou a usar o Self Balancing BST em vez de uma lista vinculada para encadeamento. A vantagem do bst com autobalanceamento é que obtemos o pior caso (quando todas as teclas são mapeadas para o mesmo slot), o tempo de pesquisa é O (Log n).
HashMap sincronizado
Como é dito que o HashMap não está sincronizado, ou seja, vários threads podem acessá-lo simultaneamente. Se vários threads acessam essa classe simultaneamente e pelo menos um thread a manipula estruturalmente, é necessário sincronizá-la externamente. Isso é feito sincronizando algum objeto que encapsula o mapa. Se esse objeto não existir, ele pode ser agrupado em Collections.synchronizedMap() para tornar o HashMap sincronizado e evitar o acesso não sincronizado acidental. Como no exemplo a seguir:
Map m = Collections.synchronizedMap(new HashMap(...));
Agora o Mapa m está sincronizado. Os iteradores desta classe são rápidos para falhas se qualquer modificação da estrutura for feita após a criação do iterador, de qualquer forma, exceto por meio do método remove do iterador. Em uma falha do iterador, ele lançará ConcurrentModificationException.
Complexidade de tempo do HashMap: o HashMap fornece complexidade de tempo constante para operações básicas, obtenha e coloque se a função hash está gravada corretamente e dispersa os elementos adequadamente entre os baldes. A iteração no HashMap depende da capacidade do HashMap e de vários pares de valores-chave. Basicamente, é diretamente proporcional à capacidade + tamanho. A capacidade é o número de depósitos no HashMap. Portanto, não é uma boa ideia manter um grande número de depósitos no HashMap inicialmente.
Aplicações de HashMap:HashMap é principalmente a implementação de hashing. É útil quando precisamos de uma implementação eficiente de operações de pesquisa, inserção e exclusão. Consulte os aplicativos de hashing para obter detalhes.
Métodos em HashMap
- K - o tipo das chaves no mapa.
- V - Tipo de valores mapeados no mapa.
MÉTODO | DESCRIÇÃO |
---|---|
Claro() | Remove todos os mapeamentos deste mapa. |
clone() | Retorna uma cópia superficial desta instância de HashMap: as chaves e os valores em si não são clonados. |
compute (tecla K, BiFunção <? super K ,? super V ,? extends V> remapeamentoFunção) | Tenta calcular um mapeamento para a chave especificada e seu valor mapeado atual (ou nulo se não houver mapeamento atual). |
computeIfAbsent (tecla K, Função <? super K ,? extends V> mappingFunction) | Se a chave especificada ainda não estiver associada a um valor (ou estiver mapeada para nulo), tenta calcular seu valor usando a função de mapeamento fornecida e o insere neste mapa, a menos que seja nulo. |
computeIfPresent (K key, BiFunction <? super K ,? super V ,? extends V> remappingFunction) | Se o valor da chave especificada estiver presente e não for nulo, tenta calcular um novo mapeamento, dada a chave e seu valor mapeado atual. |
containsKey (chave do objeto) | Retorna verdadeiro se este mapa contém um mapeamento para a chave especificada. |
containsValue (valor do objeto) | Retorna verdadeiro se este mapa mapeia uma ou mais chaves para o valor especificado. |
entrySet() | Retorna uma visualização Set dos mapeamentos contidos neste mapa. |
get (chave do objeto) | Retorna o valor para o qual a chave especificada é mapeada ou nulo se este mapa não contém mapeamento para a chave. |
está vazia() | Retorna verdadeiro se este mapa não contém mapeamentos de valores-chave. |
conjunto de chaves() | Retorna uma visualização Set das chaves contidas neste mapa. |
mesclar (tecla K, valor V, BiFunção < ? super V,? super V ,? estende V> função remapeamento) | Se a chave especificada ainda não estiver associada a um valor ou estiver associada a nulo, associa-a ao valor não nulo fornecido. |
colocar (chave K, valor V) | Associa o valor especificado à chave especificada neste mapa. |
putAll (Map <? estende K ,? estende V> m) | Copia todos os mapeamentos do mapa especificado para este mapa. |
remover (chave do objeto) | Remove o mapeamento para a chave especificada deste mapa, se presente. |
Tamanho() | Retorna o número de mapeamentos de valores-chave neste mapa. |
valores() | Retorna uma visualização de Coleção dos valores contidos neste mapa. |
Métodos herdados da classe java.util.AbstractMap
MÉTODO | DESCRIÇÃO |
---|---|
é igual a() | Compara o objeto especificado com este mapa para igualdade. |
hashCode() | Retorna o valor do código hash para este mapa. |
para sequenciar() | Retorna uma representação de string deste mapa. |
Métodos herdados da interface java.util.Map
MÉTODO | DESCRIÇÃO |
---|---|
é igual a() | Compara o objeto especificado com este mapa para igualdade. |
forEach (BiConsumer <? super K, ? super V> ação) | Executa a ação fornecida para cada entrada neste mapa até que todas as entradas tenham sido processadas ou a ação lance uma exceção. |
getOrDefault (chave do objeto, V defaultValue) | Retorna o valor para o qual a chave especificada é mapeada ou defaultValue se este mapa não contiver mapeamento para a chave. |
hashCode() | Retorna o valor do código hash para este mapa. |
putIfAbsent (chave K, valor V) | Se a chave especificada ainda não estiver associada a um valor (ou estiver mapeada para nulo), a associa ao valor fornecido e retorna nulo, caso contrário, retorna o valor atual. |
remove (chave do objeto, valor do objeto) | Remove a entrada para a chave especificada apenas se ela estiver atualmente mapeada para o valor especificado. |
substituir (chave K, valor V) | Substitui a entrada da chave especificada apenas se ela estiver mapeada para algum valor. |
substituir (chave K, V antigoValor, V novoValor) | Substitui a entrada da chave especificada apenas se atualmente mapeada para o valor especificado. |
replaceAll (BiFunction <? super K, ? super V ,? estende V> função) | Substitui o valor de cada entrada com o resultado de invocar a função fornecida nessa entrada até que todas as entradas tenham sido processadas ou a função lance uma exceção. |
Deve ler:
Este artigo foi contribuído por Vishal Garg . Se você gosta de GeeksforGeeks e gostaria de contribuir, você também pode escrever um artigo usando write.geeksforgeeks.org ou enviar seu artigo para review-team@geeksforgeeks.org. Veja o seu artigo na página principal do GeeksforGeeks e ajude outros Geeks. Escreva comentários se encontrar algo incorreto ou se quiser compartilhar mais informações sobre o tópico discutido acima.
As postagens do blog Acervo Lima te ajudaram? Nos ajude a manter o blog no ar!
Faça uma doação para manter o blog funcionando.
70% das doações são no valor de R$ 5,00...
Diógenes Lima da Silva