Classificar um HashMap em Java
1. Introdução
Neste tutorial rápido, aprenderemos comosort a HashMap in Java.
Mais especificamente, veremos como classificar entradas deHashMap por sua chave ou valor usando:
-
TreeMap
-
ArrayList eCollections.sort()
-
TreeSet
-
Usando a APIStream,e, finalmente,
-
Usando a bibliotecaGuava
2. Usando umTreeMap
Como sabemos,keys in TreeMap are sorted using their natural order. Essa é uma boa solução quando queremos classificar os pares de valor-chave por sua chave. Portanto, a ideia é enviar todos os dados de nossoHashMap paraTreeMap.
Para começar, vamos definir umHashMape inicializá-lo com alguns dados:
Map map = new HashMap<>();
Employee employee1 = new Employee(1L, "Mher");
map.put(employee1.getName(), employee1);
Employee employee2 = new Employee(22L, "Annie");
map.put(employee2.getName(), employee2);
Employee employee3 = new Employee(8L, "John");
map.put(employee3.getName(), employee3);
Employee employee4 = new Employee(2L, "George");
map.put(employee4.getName(), employee4);
Para a classeEmployee,note that we’ve implemented Comparable:
public class Employee implements Comparable {
private Long id;
private String name;
// constructor, getters, setters
// override equals and hashCode
@Override
public int compareTo(Employee employee) {
return (int)(this.id - employee.getId());
}
}
Em seguida, armazenamos as entradas emTreeMap usando seu construtor:
TreeMap sorted = new TreeMap<>(map);
Ou o métodoputAll para copiar os dados:
TreeMap sorted = new TreeMap<>();
sorted.putAll(map);
E é isso! Para garantir que nossas entradas de mapa sejam classificadas por chave, vamos imprimi-las:
Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}
Como vemos, as chaves são classificadas em ordem natural.
3. UsandoArrayList
Claro, podemos classificar as entradas do mapa com a ajuda deArrayList. A principal diferença em relação ao método anterior é quewe don’t maintain the Map interface here.
3.1. Classificar por chave
Vamos carregar o conjunto de chaves em umArrayList:
List employeeByKey = new ArrayList<>(map.keySet());
Collections.sort(employeeByKey);
E a saída é:
[Annie, George, John, Mher]
3.2. Classificar por valor
Agora, e se quisermos classificar os valores do nosso mapa pelo campoid do objetoEmployee? Podemos usar umArrayList para isso também.
Primeiro, vamos copiar os valores para a lista:
List employeeById = new ArrayList<>(map.values());
E depois disso, nós classificamos:
Collections.sort(employeeById);
Lembre-se de que isso funciona porqueEmployee implements the Comparable interface. Caso contrário, precisaríamos definir um comparador manual para nossa chamada paraCollections.sort.
Para verificar os resultados, imprimimos oemployeeById:
[Employee{id=1, name='Mher'},
Employee{id=2, name='George'},
Employee{id=8, name='John'},
Employee{id=22, name='Annie'}]
Como vemos, os objetos são classificados por seus camposid.
4. Usando umTreeSet
Caso nósdon’t want to accept duplicate values in our sorted collection, there is a nice solution with TreeSet.
Primeiro, vamos adicionar algumas entradas duplicadas ao nosso mapa inicial:
Employee employee5 = new Employee(1L, "Mher");
map.put(employee5.getName(), employee5);
Employee employee6 = new Employee(22L, "Annie");
map.put(employee6.getName(), employee6);
4.1. Classificar por chave
Para classificar o mapa por suas entradas principais:
SortedSet keySet = new TreeSet<>(map.keySet());
Vamos imprimir okeySete ver o resultado:
[Annie, George, John, Mher]
Agora, temos as chaves do mapa classificadas sem as duplicatas.
4.2. Classificar por valor
Da mesma forma, para os valores do mapa, o código de conversão se parece com:
SortedSet values = new TreeSet<>(map.values());
E os resultados são:
[Employee{id=1, name='Mher'},
Employee{id=2, name='George'},
Employee{id=8, name='John'},
Employee{id=22, name='Annie'}]
Como podemos ver, não há duplicatas na saída. This works with custom objects when we override equals and hashCode.
5. Usando Lambdas e Streams
Since the Java 8, we can use the Stream API and lambda expressions to sort the map. Tudo o que precisamos é chamar o métodosorted sobre a linha spipelinestream do mapa.
5.1. Classificar por chave
Para classificar por chave, usamos o scomparatorcomparingByKey :
map.entrySet()
.stream()
.sorted(Map.Entry.comparingByKey())
.forEach(System.out::println);
O estágio finalforEach imprime os resultados:
Annie=Employee{id=22, name='Annie'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Mher=Employee{id=1, name='Mher'}
Por padrão, o modo de classificação está em ascensão.
5.2. Classificar por valor
Claro, podemos classificar pelos objetosEmployee também:
map.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.forEach(System.out::println);
Como podemos ver, o código acima imprime um mapa classificado pelos camposid de objetosEmployee:
Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}
Além disso, podemos coletar os resultados em um novo mapa:
Map result = map.entrySet()
.stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldValue, newValue) -> oldValue, LinkedHashMap::new));
Note that we collected our results into a LinkedHashMap. Por padrão,Collectors.toMap retorna um novo HashMap, mas como sabemos,HashMap doesn’t guarantee iterationorder, enquantoLinkedHashMap o faz.
6. Usando goiaba
Por último, uma biblioteca que nos permite ordenarHashMap é a Guava. Antes de começar, será útil verificar nosso artigo sobremaps in Guava.
Primeiro, vamos declarar umOrdering, pois queremos classificar nosso mapa pelo campoEmployee’sId:
Ordering naturalOrdering = Ordering.natural()
.onResultOf(Functions.forMap(map, null));
Agora, tudo o que precisamos é usarImmutableSortedMap para ilustrar os resultados:
ImmutableSortedMap.copyOf(map, naturalOrdering);
E mais uma vez, a saída é um mapa ordenado pelo campoid:
Mher=Employee{id=1, name='Mher'}
George=Employee{id=2, name='George'}
John=Employee{id=8, name='John'}
Annie=Employee{id=22, name='Annie'}
7. Sumário
Neste artigo, revisamos várias maneiras de classificar uma chaveHashMap by ou por valor.
E examinamos de perto como podemos fazer isso quando o atributo é uma classe personalizada, implementandoComparable.
Finalmente, como sempre, o código usado durante a discussão pode ser encontradoover on GitHub.