O LinkedHashMap é como o HashMap, com um recurso adicional de manter uma ordem dos elementos inseridos nele. O HashMap oferece a vantagem de inserção, pesquisa e exclusão rápidas, mas nunca mantém o controle e a ordem de inserção que o LinkedHashMap fornece, onde os elementos podem ser acessados ​​em sua ordem de inserção. 

Recursos importantes de um LinkedHashMap:

  • Um LinkedHashMap contém valores baseados na chave. Ele implementa a interface Map e estende a classe HashMap .
  • Ele contém apenas elementos únicos.
  • Ele pode ter uma chave nula e vários valores nulos.
  • Não está sincronizado.
  • É o mesmo que HashMap com um recurso adicional que mantém a ordem de inserção. Por exemplo, quando executamos o código com um HashMap, obtemos uma ordem diferente de elementos.

Declaração:

public class LinkedHashMap<K,​V> extends HashMap<K,​V> implements Map<K,​V>

Aqui, K é o tipo de objeto chave e V é o tipo de objeto de valor.

A hierarquia de LinkedHashMap

LinkedHashMap em Java

Ele implementa a interface Map <K, V> e estende a classe HashMap <K, V> .

Construtores de LinkedHashMap

Para criar um LinkedHashMap , precisamos criar um objeto da classe LinkedHashMap. A classe LinkedHashMap consiste em vários construtores que permitem a possível criação do ArrayList. A seguir estão os construtores disponíveis nesta classe:

1. LinkedHashMap(): Isso é usado para construir um construtor LinkedHashMap padrão.

LinkedHashMap <K, V> lhm = novo LinkedHashMap <K, V>();

2. LinkedHashMap (capacidade interna): É usado para inicializar um LinkedHashMap específico com uma capacidade especificada.

LinkedHashMap <K, V> lhm = novo LinkedHashMap <K, V> (capacidade interna);

3. LinkedHashMap (Mapa <? Estende K ?, Estende V > mapa ): É usado para inicializar um LinkedHashMap particular, com os elementos do mapa especificado.

LinkedHashMap <K, V> lhm = novo LinkedHashMap <K, V> (Map <? Extends K,? Extends V> mapa);

4. LinkedHashMap (int capacity, float fillRatio): É usado para inicializar a capacidade e a taxa de preenchimento de um LinkedHashMap. Um fillRatio também chamado de loadFactor é uma métrica que determina quando aumentar o tamanho do LinkedHashMap automaticamente. Por padrão, esse valor é 0,75, o que significa que o tamanho do mapa aumenta quando o mapa está 75% cheio.

LinkedHashMap <K, V> lhm = novo LinkedHashMap <K, V> (capacidade interna, float fillRatio);

5. LinkedHashMap (int capacity, float fillRatio, boolean Order): Este construtor também é usado para inicializar a capacidade e a taxa de preenchimento de um LinkedHashMap junto com o fato de seguir a ordem de inserção ou não.

LinkedHashMap <K, V> lhm = novo LinkedHashMap <K, V> (capacidade interna, float fillRatio, ordem booleana);

Aqui, o atributo For Order, true é passado para o último pedido de acesso e false é passado para o pedido de inserção.

Exemplo: A implementação a seguir demonstra como criar e usar um LinkedHashMap.
 

// Java program to demonstrate working of LinkedHashMap
  
import java.util.*;
  
public class LinkedHashMapExample {
    
    public static void main(String a[])
    {
        // create an instance of LinkedHashMap
        LinkedHashMap<String, String> lhm
            = new LinkedHashMap<String, String>();
  
        // Add mappings using put method
        lhm.put("one", "practice.geeksforgeeks.org");
        lhm.put("two", "code.geeksforgeeks.org");
        lhm.put("four", "quiz.geeksforgeeks.org");
  
        // It prints the elements in same order
        // as they were inserted
        System.out.println(lhm);
  
        System.out.println("Getting value for key 'one': "
                           + lhm.get("one"));
  
        System.out.println("Size of the map: "
                           + lhm.size());
  
        System.out.println("Is map empty? "
                           + lhm.isEmpty());
  
        System.out.println("Contains key 'two'? "
                           + lhm.containsKey("two"));
  
        System.out.println(
            "Contains value 'practice.geeks"
            + "forgeeks.org'? "
            + lhm.containsValue("practice"
                                + ".geeksforgeeks.org"));
  
        System.out.println("delete element 'one': "
                           + lhm.remove("one"));
  
        // print mappings to the console
        System.out.println("Mappings of LinkedHashMap : "
                           + lhm);
    }
}
Saída
{one = practice.geeksforgeeks.org, two = code.geeksforgeeks.org, four = quiz.geeksforgeeks.org}
Obtendo valor para a chave 'um': practice.geeksforgeeks.org
Tamanho do mapa: 3
O mapa está vazio? falso
Contém a chave 'dois'? verdade
Contém o valor 'practice.geeksforgeeks.org'? verdade
exclua o elemento 'um': practice.geeksforgeeks.org
Mapeamentos de LinkedHashMap: {two = code.geeksforgeeks.org, four = quiz.geeksforgeeks.org}

Executar várias operações na classe HashMap

Vamos ver como realizar algumas operações usadas com frequência no LinkedHashMap.

1. Adicionando Elementos: Para adicionar um elemento ao LinkedHashMap, podemos usar o método put(). Isso é diferente do HashMap porque no HashMap , a ordem de inserção não é retida, mas é retida no LinkedHashMap. 

// Java program to demonstrate adding
// elements to a LinkedHashMap
  
import java.util.*;
  
class AddElementsToLinkedHashMap {
  
    public static void main(String args[])
    {
  
        // Initialization of a LinkedHashMap
        // using Generics
        LinkedHashMap<Integer, String> hm1
            = new LinkedHashMap<Integer, String>();
  
        // Add mappings using
        // put() method
        hm1.put(3, "Geeks");
        hm1.put(2, "For");
        hm1.put(1, "Geeks");
  
        // print mappings to the console
        System.out.println("Mappings of LinkedHashMap : "
                           + hm1);
    }
}
Saída
Mapeamentos de LinkedHashMap: {3 = Geeks, 2 = For, 1 = Geeks}

2. Alterando Elementos: Depois de adicionar os elementos, se desejarmos alterar o elemento, isso pode ser feito adicionando novamente o elemento com o método put(). Uma vez que os elementos no mapa de árvore 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 demonstrate
// changing/updating of LinkedHashMap
  
import java.util.*;
  
class UpdatingLinkedHashMap {
  
    public static void main(String args[])
    {
        // Initialization of a LinkedHashMap
        // using Generics
        LinkedHashMap<Integer, String> hm
            = new LinkedHashMap<Integer, String>();
  
        // Insert mappings using put() method
        hm.put(3, "Geeks");
        hm.put(2, "Geeks");
        hm.put(1, "Geeks");
  
        // print mappings to the console
        System.out.println("Initial map : " + hm);
  
        // Update the value with key 2
        hm.put(2, "For");
  
        // print the updated map
        System.out.println("Updated Map : " + hm);
    }
}
Saída
Mapa inicial: {3 = Geeks, 2 = Geeks, 1 = Geeks}
Mapa atualizado: {3 = Geeks, 2 = For, 1 = Geeks}

3. Removendo Elemento: Para remover um elemento do TreeMap , podemos usar o método remove(). Este método pega o valor da chave e remove o mapeamento da chave deste mapa de árvore, se estiver presente no mapa. Além disso, também podemos remover o primeiro elemento inserido do mapa se o tamanho máximo for definido conforme discutido neste artigo
 

// Java program to demonstrate the
// removing of elements from LinkedHashMap
  
import java.util.*;
  
class RemovingMappingsFromLinkedHashMap {
    public static void main(String args[])
    {
        // Initialization of a LinkedHashMap
        // using Generics
        LinkedHashMap<Integer, String> hm
            = new LinkedHashMap<Integer, String>();
  
        // Inserting the Elements
        // using put() method
        hm.put(3, "Geeks");
        hm.put(2, "Geeks");
        hm.put(1, "Geeks");
        hm.put(4, "For");
  
        // print the mappings to the console
        System.out.println("Initial Map : " + hm);
  
        // Remove the mapping with Key 4
        hm.remove(4);
  
        // print the updated map
        System.out.println("Updated Map : " + hm);
    }
}
Saída
Mapa inicial: {3 = Geeks, 2 = Geeks, 1 = Geeks, 4 = For}
Mapa atualizado: {3 = Geeks, 2 = Geeks, 1 = Geeks}

4. Iterando por meio do LinkedHashMap: Existem várias maneiras de iterar por meio do Mapa. A maneira mais famosa é usar um loop for-each e obter as chaves. O valor da chave é encontrado usando o método getValue() .
 

// Java program to demonstrate
// iterating over LinkedHashMap
  
import java.util.*;
class IteratingOverLinkedHashMap {
    public static void main(String args[])
    {
        // Initialization of a LinkedHashMap
        // using Generics
        LinkedHashMap<Integer, String> hm
            = new LinkedHashMap<Integer, String>();
  
        // Inserting the Elements
        hm.put(3, "Geeks");
        hm.put(2, "For");
        hm.put(1, "Geeks");
  
        for (Map.Entry<Integer, String> mapElement : hm.entrySet()) {
  
            Integer key = mapElement.getKey();
  
            // Finding the value
            String value = mapElement.getValue();
  
            // print the key : value pair
            System.out.println(key + " : " + value);
        }
    }
}
Saída
3: Geeks
2: para
1: Geeks

Como o LinkedHashMap funciona internamente?

Um LinkedHashMap é uma extensão da classe HashMap e implementa a interface Map . Portanto, a classe é declarada como:
 

public class LinkedHashMap extends HashMap implementa Map 
 

Nesta classe, os dados são armazenados na forma de nós. A implementação do LinkedHashMap é muito semelhante a uma lista duplamente vinculada . Portanto, cada nó do LinkedHashMap é representado como:
 

LinkedHashMap-Node-in-Java

  • Hash: Todas as chaves de entrada são convertidas em um hash, que é uma forma mais curta da chave para que a pesquisa e a inserção sejam mais rápidas.
  • Chave: como essa classe estende o HashMap, os dados são armazenados na forma de um par de valores-chave. Portanto, esse parâmetro é a chave dos dados.
  • Valor: para cada chave, existe um valor associado a ela. Este parâmetro armazena o valor das chaves. Devido aos genéricos, esse valor pode ser de qualquer forma.
  • Próximo: Como o LinkedHashMap armazena o pedido de inserção, ele contém o endereço do próximo nó do LinkedHashMap.
  • Anterior: Este parâmetro contém o endereço do nó anterior do LinkedHashMap.
     

LinkedHashMap sincronizado

A implementação de LinkedHashMap não sincronizada. Se vários threads acessam um mapa hash vinculado simultaneamente e pelo menos um dos threads modifica o mapa estruturalmente, ele deve ser sincronizado externamente. Isso normalmente é realizado por meio da sincronização em algum objeto que encapsula naturalmente o mapa. Se tal objeto não existir, o mapa deve ser “empacotado” usando o método Collections.synchronizedMap . Isso é feito melhor no momento da criação, para evitar o acesso não sincronizado acidental ao mapa:

  Mapa m = Collections.synchronizedMap (novo LinkedHashMap (…));

Métodos de LinkedHashMap 

  • K - o tipo das chaves no mapa.
  • V - Tipo de valores mapeados no mapa.

MÉTODO

DESCRIÇÃO

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.
conjunto de chaves()Retorna uma visualização Set das chaves contidas neste mapa.
removeEldestEntry (Map.Entry <K, V> mais antigo)Retorna verdadeiro se este mapa deve remover sua entrada mais antiga.
valores()Retorna uma visualização de Coleção dos valores contidos neste mapa.

Métodos declarados na classe java.util.HashMap

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 <? extends K,? extends 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 declarados na classe java.util.AbstractMap

MÉTODO



DESCRIÇÃO

é igual a (objeto o)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 declarados na interface java.util.Map

MÉTODO

DESCRIÇÃO

 Claro()Remove todos os mapeamentos deste mapa (operação opcional).
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.
é igual a (objeto o)Compara o objeto especificado com este mapa para igualdade.
forEach (ação BiConsumer <? super K,? super V>)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.
está vazia()Retorna verdadeiro se este mapa não contém mapeamentos de valores-chave.
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 (operação opcional).
putAll (Map <? extends K,? extends V> m)Copia todos os mapeamentos do mapa especificado para este mapa (operação opcional).
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.
remover (chave do objeto)Remove o mapeamento de uma chave deste mapa, se estiver presente (operação opcional).
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.
substituirAll (BiFunction <? super K,? super V,? extends 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.
Tamanho()Retorna o número de mapeamentos de valores-chave neste mapa.

Aplicação: Uma vez que LinkedHashMap usa Doubly LinkedList para manter a ordem de inserção, podemos implementar a funcionalidade LRU Cache substituindo o método removeEldestEntry() para impor uma política para remover automaticamente obsoleto quando novos mapeamentos são adicionados ao mapa. Isso permite que você expire os dados usando alguns critérios que você definir.

Referência: https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/LinkedHashMap.html

Artigos relacionados: