Musisz przeciążyć metody equals i hashCode w klasie Osoba. W NetBeansie ustaw kursor w środku klasy Osoba, naciśnij Lewy Alt + Insert i wybierz Generate equals and hashCode. Potem wybierz pola które powinny być brane pod uwagę. Zaleca się, aby do equals i hashCode wybrać te same pola. Ja wybrałem wszystkie pola z klasy, czyli imię i nazwisko.
import java.util.HashMap;
import java.util.Map;
public class Main {
public class Osoba {
private String imię;
private String nazwisko;
public Osoba(String imię, String nazwisko) {
this.imię = imię;
this.nazwisko = nazwisko;
}
public String getImię() {
return imię;
}
public String getNazwisko() {
return nazwisko;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Osoba other = (Osoba) obj;
if ((this.imię == null) ? (other.imię != null) : !this.imię.equals(other.imię)) {
return false;
}
if ((this.nazwisko == null) ? (other.nazwisko != null) : !this.nazwisko.equals(other.nazwisko)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = 5;
hash = 59 * hash + (this.imię != null ? this.imię.hashCode() : 0);
hash = 59 * hash + (this.nazwisko != null ? this.nazwisko.hashCode() : 0);
return hash;
}
}
public void run() {
Map<Integer, Osoba> mapa = new HashMap<Integer, Osoba>();
mapa.put(1, new Osoba("Jan", "Kowalski"));
mapa.put(2, new Osoba("Adam", "Nowak"));
System.out.println(mapa.containsValue(new Osoba("Jan", "Kowalski")));
}
public static void main(String[] args) {
new Main().run();
}
}
Poza tym pamiętaj, że metoda containsKey() ma złożoność średnią równą O(1) (tzn zabiera stały czas, w tym przypadku bardzo krótki) ponieważ klucze są hashowane, containsValue() natomiast ma złożność średnią równą O(n) (tzn zabiera czas proporcjonalny do ilości elementów w mapie) bo trzeba sprawdzić wszystkie pozycje dlatego, że wartości nie są hashowane - HashMap to mapa jednostronna. Czuję, że nie wiesz w ogóle jak HashMap działa i jak się tego powinno używać.
Metoda containsValue() nie korzysta z hashCode(), ponieważ to klucze są hashowane, a nie wartości. Wobec tego jeżeli w powyższym kodzie klasa Osoba zwraca za każdym razem inny hashCode to kod dalej będzie dobrze działał:
import java.util.HashMap;
import java.util.Map;
public class Main {
public static class Osoba {
private String imię;
private String nazwisko;
public Osoba(String imię, String nazwisko) {
this.imię = imię;
this.nazwisko = nazwisko;
}
public String getImię() {
return imię;
}
public String getNazwisko() {
return nazwisko;
}
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Osoba other = (Osoba) obj;
if ((this.imię == null) ? (other.imię != null) : !this.imię.equals(other.imię)) {
return false;
}
if ((this.nazwisko == null) ? (other.nazwisko != null) : !this.nazwisko.equals(other.nazwisko)) {
return false;
}
return true;
}
static volatile int licznik = 0;
@Override
public int hashCode() {
synchronized (Osoba.class) {
licznik++;
return licznik;
}
}
}
public void run() {
Map<Integer, Osoba> mapa = new HashMap<Integer, Osoba>();
mapa.put(1, new Osoba("Jan", "Kowalski"));
mapa.put(2, new Osoba("Adam", "Nowak"));
System.out.println(mapa.containsValue(new Osoba("Jan", "Kowalski")));
}
public static void main(String[] args) {
new Main().run();
}
}
Ten kod działa w pełni poprawnie ponieważ:
- kluczami są Integery, a klasa Integer poprawnie implementuje metody equals() i hashCode()
- wartościami są Osoby, a klasa Osoba poprawnie implementuje metodę equals()