Classificação de Map por valores em Java: como não pisar nos mesmos ancinhos (e nos novos também)
\n\n«Preciso classificar um HashMap por valores!» — esta pergunta no Stack Overflow acumula milhares de visualizações e dezenas de respostas. Parece que poderia ser mais simples? Pegue um Map, classifique por values()… e ganhe uma dor de cabeça. Porque classificar um Map por valores em Java é aquela tarefa onde iniciantes (e até desenvolvedores experientes) cometem os mesmos erros repetidamente.
Neste artigo, analisaremos os 5 erros mais comuns ao classificar HashMap por valores, mostraremos as soluções corretas e forneceremos modelos de código prontos. Vamos lá!
\n\nErro nº1: Tentativa ingênua de classificar o próprio HashMap
\n\nO erro mais comum é pensar que um HashMap pode ser classificado "no local". HashMap não garante a ordem dos elementos — esta é sua propriedade fundamental. Você não pode simplesmente chamar sort() em um HashMap, porque ele não possui esse método.
Veja como NÃO fazer:
\n\n// ❌ ERRO: HashMap não pode ser classificado diretamente\nMap<String, Integer> scores = new HashMap<>();\nscores.put("Alice", 95);\nscores.put("Bob", 80);\nscores.put("Charlie", 90);\n\n// Este método não existe!\n// scores.sort(...); // Erro de compilação\n\nPor que isso não funciona? HashMap usa hashing para armazenar pares chave-valor. A ordem é determinada pelos códigos hash das chaves e pode mudar ao adicionar novos elementos. Classificar um Map por valores só é possível criando uma nova estrutura de dados — por exemplo, LinkedHashMap.
Solução correta: criando um novo LinkedHashMap
\n\n// ✅ CORRETO: classificamos Entry e salvamos em LinkedHashMap\nMap<String, Integer> sortedMap = scores.entrySet()\n .stream()\n .sorted(Map.Entry.comparingByValue())\n .collect(Collectors.toMap(\n Map.Entry::getKey,\n Map.Entry::getValue,\n (e1, e2) -> e1, // resolvendo conflitos (se houver chaves duplicadas)\n LinkedHashMap::new // mantendo a ordem de inserção\n ));\n\nSystem.out.println(sortedMap);\n// {Bob=80, Charlie=90, Alice=95} — classificado em ordem crescente!\n\nErro nº2: Esquecer o LinkedHashMap ao coletar
\n\nAté desenvolvedores Java experientes às vezes escrevem este código:
\n\n// ⚠️ QUASE CORRETO, mas tem um detalhe\nMap<String, Integer> result = scores.entrySet()\n .stream()\n .sorted(Map.Entry.comparingByValue())\n .collect(Collectors.toMap(\n Map.Entry::getKey,\n Map.Entry::getValue\n )); // Por padrão, Collectors.toMap() cria um HashMap!\n\nQual é o problema? Collectors.toMap() sem especificar um fornecedor (supplier) cria um HashMap. E HashMap não garante ordem! Sua classificação será executada, mas o resultado pode parecer não classificado. Este é um dos erros mais traiçoeiros em Java ao classificar Map.
Como corrigir
\n\nSempre especifique explicitamente LinkedHashMap::new como quarto argumento:
// ✅ GARANTIDAMENTE CORRETO\nMap<String, Integer> result = scores.entrySet()\n .stream()\n .sorted(Map.Entry.comparingByValue())\n .collect(Collectors.toMap(\n Map.Entry::getKey,\n Map.Entry::getValue,\n (oldVal, newVal) -> oldVal,\n LinkedHashMap::new // Ponto crucial!\n ));\n\nErro nº3: Classificar por valores quando eles não são Comparable
\n\nSuponha que você tenha Map<String, CustomObject>. Você escreve:
// ❌ ERRO: CustomObject não implementa Comparable\nMap<String, CustomObject> map = new HashMap<>();\n// ...\nmap.entrySet().stream()\n .sorted(Map.Entry.comparingByValue()) // Erro de compilação!\n