Médio Java
Chave composta em HashMap
Enunciado
Crie uma classe Chave que representa uma chave composta por dois campos String. Sobrescreva equals e hashCode corretamente. Use essa chave em um HashMap para associar a um valor inteiro. Teste inserir duas chaves iguais e verificar que o valor é sobrescrito.
Requisitos
- A classe
Chavedeve ter dois camposString(ex.:parte1eparte2). equalsdeve comparar ambos os campos usandoObjects.equals.hashCodedeve usarObjects.hashcom ambos os campos.- O programa deve demonstrar que duas chaves iguais acessam o mesmo valor no
HashMap.
Código inicial
import java.util.*;
class Chave {
private String parte1, parte2;
Chave(String parte1, String parte2) {
this.parte1 = parte1;
this.parte2 = parte2;
}
// TODO: equals e hashCode
}
public class Main {
public static void main(String[] args) {
Map<Chave, Integer> mapa = new HashMap<>();
Chave k1 = new Chave("a", "b");
Chave k2 = new Chave("a", "b");
mapa.put(k1, 10);
mapa.put(k2, 20);
System.out.println("Valor para k1: " + mapa.get(k1));
System.out.println("Tamanho do mapa: " + mapa.size());
}
}
Saída esperada
Valor para k1: 20
Tamanho do mapa: 1
Ver dica
Lembre-se de que Objects.equals e Objects.hash aceitam múltiplos argumentos.
Mostrar solução
import java.util.*;
class Chave {
private String parte1, parte2;
Chave(String parte1, String parte2) {
this.parte1 = parte1;
this.parte2 = parte2;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Chave chave = (Chave) o;
return Objects.equals(parte1, chave.parte1) &&
Objects.equals(parte2, chave.parte2);
}
@Override
public int hashCode() {
return Objects.hash(parte1, parte2);
}
}
public class Main {
public static void main(String[] args) {
Map<Chave, Integer> mapa = new HashMap<>();
Chave k1 = new Chave("a", "b");
Chave k2 = new Chave("a", "b");
mapa.put(k1, 10);
mapa.put(k2, 20);
System.out.println("Valor para k1: " + mapa.get(k1));
System.out.println("Tamanho do mapa: " + mapa.size());
}
}
Passo a passo
- A classe
Chavearmazena duas strings que compõem a chave. - No
equals, verificamos identidade, nulidade e classe, depois comparamos cada campo comObjects.equals, que tratanull. - No
hashCode, usamosObjects.hash(parte1, parte2)para gerar um hash baseado nos mesmos campos. - No
main, criamos duas chaves iguais e as inserimos noHashMap. - Como são iguais, a segunda inserção sobrescreve o valor da primeira.
- O
getcomk1retorna o valor atualizado (20) e o tamanho do mapa é 1.
Por que funciona
O HashMap usa hashCode para localizar o balde e equals para comparar chaves. Como k1 e k2 são iguais e têm o mesmo hash, o mapa as considera a mesma chave, sobrescrevendo o valor. Isso demonstra o contrato na prática.
Erros comuns
- Não sobrescrever
hashCode: o mapa tratariak1ek2como chaves diferentes, resultando em tamanho 2 eget(k1)retornando 10. - Usar
==para comparar strings:parte1 == chave.parte1compara referências, não conteúdo. UseObjects.equals. - Esquecer de tratar
null: separte1for nulo,parte1.equals(...)lançariaNullPointerException.Objects.equalsevita isso.
Outra forma de resolver
Usar Map.Entry ou uma record como chave:
record Chave(String parte1, String parte2) {}
Records geram equals e hashCode automaticamente, sendo mais conciso e menos propenso a erros.
Saída esperada
Valor para k1: 20
Tamanho do mapa: 1