HOWTO · Java

Classificar um HashMap por chave em Java

Este artigo apresenta como classificar um HashMap por chave em Java.

Nesta página

O termo HashMap na linguagem Java é a coleção derivada da interface Map. Esta coleção ou classe está presente no pacote java.util e armazena os dados no par de valor-chave. Observe que não pode haver duas chaves no mapa. Se a chave duplicada for inserida, o valor da chave respectiva será substituído pelo valor mais recente.

Classifique o conjunto de chaves usando a classe TreeMap em Java

Abaixo está o bloco de código para demonstrar a classificação de um HashMap por sua chave.

import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class HashMapSortByKey {
  public static void main(String[] args) {
    Map<String, String> map = new HashMap<>();
    map.put("2", "Value5");
    map.put("3", "Value1");
    map.put("1", "Value2");
    map.put("4", "Value3");
    map.put("9", "Value4");
    map.put("hi11", "Value6");
    map.put("hi0", "Value7");
    System.out.print("Unordered List: ");
    for (String s : map.keySet()) {
      System.out.print(" " + s);
    }
    System.out.println();
    System.out.print("Ordered List: ");
    TreeMap<String, String> map1 = new TreeMap<>(map);
    for (String s : map1.keySet()) {
      System.out.print(" " + s);
    }
  }
}

No bloco de código acima, o objeto map é declarado usando o construtor padrão de HashMap com a palavra-chave new. A instrução cria uma instância da classe HashSet e atribui o valor à referência de interface Map. Os tipos são compatíveis, pois a classe HashMap implementa a interface Map internamente.

O mapa é inicializado com algum conjunto de valores-chave. A inserção acontece usando o método put que vincula a chave ao seu valor especificado. O método retorna o previous value se a chave já estava presente no mapa e substitui o valor anterior por um valor especificado. A função retorna um valor null quando a chave ainda não está presente no mapa. Ele lança IllegalArgumentException se a propriedade da chave ou valor proíbe a inserção do valor.

Agora, para iterar no mapa, o loop for-each é usado. A função map.keySet retorna o formato Set de todas as chaves no mapa. A função de conjunto de chaves obtém uma coleção no loop for-each sobre a qual a variável pode iterar; portanto, imprimindo as chaves. Ele imprimirá os valores em um formato não ordenado e não há uma maneira bem definida pela qual o usuário obterá a saída.

Para classificar as chaves do mapa, a classe TreeSet é usada. A variável map é fornecida como um parâmetro do construtor no construtor TreeSet no momento da instanciação. A classe implementa a interface Comparable para ordenar as chaves. Quando o mapa resultante, map1, é impresso, ele imprime as chaves classificadas na saída.

Abaixo está a saída do bloco de código acima.

Resultado:

Unordered List:  1 hi11 2 3 4 9 hi0
Ordered List:  1 2 3 4 9 hi0 hi11

Classificando o conjunto de chaves usando as funções Java 8

Java 8 fornece um privilégio de programação funcional, o que ajuda a trabalhar com as funções da cadeia. No programa abaixo, vê-se que a instanciação e a inicialização acontecem em um comando. Enquanto no primeiro código de exemplo, é uma tarefa tediosa preencher o mapa. Compreender os Streams e as funções para instanciar o mapa em uma única instrução é fornecido abaixo.

Streams é uma interface no pacote java.util que fornece flexibilidade para trabalhar sobre a sequência de operações de uma só vez. O Streams funciona no pipeline onde um emissor emite os dados; ele é filtrado, processado, transformado e muito mais de acordo com a necessidade dos usuários.

import static java.util.AbstractMap.SimpleEntry;
import static java.util.stream.Collectors.toMap;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Stream;

public class HashMapSortByKey {
  public static void main(String[] args) {
    Map<String, String> map =
        Stream
            .of(new SimpleEntry<>("key6", "value1"), new SimpleEntry<>("key12", "value2"),
                new SimpleEntry<>("key9", "value3"))
            .collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue));

    System.out.print("Unordered List: ");
    for (String s : map.keySet()) {
      System.out.print(" " + s);
    }
    Map<String, String> mapSortedByKey =
        map.entrySet()
            .stream()
            .sorted(Map.Entry.<String, String>comparingByKey().reversed())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                (oldVal, newValue) -> oldValue, LinkedHashMap::new));

    System.out.println();
    System.out.print("Ordered List: ");
    for (String s1 : mapSortedByKey.keySet()) {
      System.out.print(" " + s1);
    }
  }
}

Compreender a função de fluxo de inicialização do mapa em Java

Em primeiro lugar, o Stream chama a função of() que retorna o fluxo especificado em ordem sequencial. A função cria objetos da classe SimpleEntry para criar mapeamentos do formulário de valor-chave. A classe implementa a interface Entry e possui o método entrySet que retorna a visualização da coleção do mapa.

Uma vez que as entradas de valor-chave são formadas, os valores são coletados em um mapa usando a função collect. É uma função terminal, o que significa que nenhum método mais pode ser invocado após a função de coleta. A função empacota ou vincula os valores de fluxo nas estruturas de dados desejadas.

A entrada fornecida como parâmetro é sempre uma referência de collect. O toMap é uma função estática na classe Collectors que retorna um Collector que liga os elementos do stream em um Mapa. A função leva um mapeador chave e um valor chave Função como seu parâmetro. Agora, o operador :: de referência de método significa chamar as funções da classe especificada.

No mapeador de chave, a função getKey extrai a chave do fluxo populado EntrySet. Da mesma forma, na função Key Value, a função getValue é chamada para obter o valor do fluxo EntrySet.

As variáveis ​​Collector Function do código acima são as interfaces funcionais em Java que têm um único método abstrato para a funcionalidade. As definições do método abstrato são definidas nas classes que as implementam.

Compreender a função Map Transformation Stream em Java

Sobre a instância map que acabou de se formar, a função entrySet é chamada. A função retorna a visualização definida das entradas do mapa e está presente na interface do mapa. Sobre essas entradas, o método stream é chamado para converter as entradas no fluxo sequencial. No fluxo de entradas, a função sorted é chamada.

É necessário um Comparator para comparar os elementos do Stream. A função classificada finalmente retorna o fluxo classificado das entradas fornecidas. A função comparingByKey retorna o comparador Map.Entry com a ordem padrão na chave. O comparador retorna um conjunto de chaves; se uma chave encontrada for nula, ele lança NullPointerException da função.

Quando o conjunto de entrada é recuperado, a função reversed é chamada para inverter a ordem dos elementos na coleção. Finalmente, a função collect é chamada sobre o fluxo do mapa. A função é um operador de terminal e, portanto, nenhuma operação pode ser chamada após a função collect. Na função, a função toMap é chamada para transformar o fluxo no mapa.

A função leva quatro parâmetros: o keyMapper é uma função que produz chaves, o valueMapper é uma função de mapeamento que cria seus valores, o mergeFunction é um BinaryOperator que mescla uma função e o mapSupplier é uma função Supplier que retorna um novo Mapa vazio onde os resultados são inseridos. Finalmente, a saída do console resultante é impressa acima.

Resultado:

Unordered List:  key12 key6 key9
Ordered List:  key9 key6 key12