Problem z HashMap

0

Mam klasę Osoba o polach imie i nazwisko
Tworzę HashMap i próbuję sprawdzić czy dane objekt istnieje w mapie.
Jednak okazuje się ,że nie istnieje.
Analogicznie ten sam kod dla mapy String działa prawidłowo.

 
java.util.HashMap<Integer,Osoba> map = new java.util.HashMap<Integer,Osoba>();
        map.put(1, new Osoba("Jan", "Kowalski"));
        map.put(2, new Osoba("Lech", "Kaczynski"));
boolean istnieje = map.containsValue(new Osoba("Lech", "Kaczynski"));
System.out.println(istnieje); // tu zwraca false a przeciesz taki sam objekt dodalem do mapy i w niej itsnieje
0

Prawda jest taka że sprawdzasz dwa różne obiekty dlatego dostajesz false. Najlepiej zrób tak:

 java.util.HashMap<Integer,Osoba> map = new java.util.HashMap<Integer,Osoba>();
	       map.put(1, new Osoba("Jan", "Kowalski"));
	       Osoba b = new Osoba("Lech", "Kaczynski");
	       map.put(2, b);
		   boolean istnieje = map.containsValue(b);
		   System.out.println(istnieje);
0

Powinieneś raczej przesłonić metody equals i hashCode w klasie Osoba

0

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()

1 użytkowników online, w tym zalogowanych: 0, gości: 1