2017-08-01 78 views
5
class Point{ 
    int x, y, l; 

    Point(int x, int y, int l){ 
     this.x =x; 
     this.y =y; 
     this.l=l; 
    } 
    @Override 
    public int hashCode() { 
     return y; 
    } 

    @Override 
    public boolean equals(final Object obj) { 
     if(this == obj) return true; 
     if(!(obj instanceof Point)) return false; 
     Point p = (Point) obj; 
     return this.x == p.x && this.y == p.y; 
    } 
} 

    TreeMap<Point,Integer> sortedMap = new TreeMap<>((p1, p2)-> p1.l-p2.l); 
    sortedMap.put(new Point(4,5,0),0); 
    sortedMap.put(new Point(5,5,0),6); 
    System.out.println(sortedMap.size()); -> Output: 1 
    System.out.println((new Point(4,5,0)).equals(new Point(5,5,0))); -> Output -> False. 

Przeładowałem oba hashcode, metoda równa się w klasie. Myślę, że metoda put powinna używać metody równości, aby określić, czy ten sam obiekt wychodzi, czy nie. Ale nie działa zgodnie z oczekiwaniami.Umieść MapMap nie działa zgodnie z oczekiwaniami

Nie jestem pewien, dlaczego mój rozmiar hashMap wynosi 1. Proszę dać mi znać, jeśli rozumiem, że nie działa źle. Pomóż mi zidentyfikować błąd w tym kodzie?

+2

Dlaczego twoja kontrola równości 'p1.l - p2.l'? –

+0

Dlaczego wywołujesz zmienną 'sortedSet', gdy nie jest to zestaw, ale mapa? –

+0

@MuratK .: To nie jest kontrola równości - to zamówienie. –

Odpowiedz

5

TreeMap używa tylko dostarczonego Comparator (lub naturalne zamawiania jeśli są dostępne) w celu ustalenia równości, tak equals i hashCode żadnej różnicy.

W twoim przypadku zarówno Point s mają tę samą wartość l, więc są uważane za identyczne zgodnie z twoją Comparator.

Możesz modyfikować swoją Comparator do podjęcia wszelkich właściwości (l, x i y) pod uwagę przy ustalaniu kolejności (i) równości swoich kluczy.

11

Twój TreeMap porównuje wartości Point przez część l (cokolwiek to miało być). To właśnie ta część swojego kodu: masz utworzone mają taką samą wartość l (0)

new TreeMap<>((p1, p2)-> p1.l-p2.l); 

Te dwa punkty, więc są one uznawane za równe ... więc drugie wywołanie put zastępuje istniejący wpis . TreeMap w ogóle nie używa equals i hashCode.

Z documentation:

Zauważ, że kolejność prowadzonego przez drzewa mapie, jak każdy posortowanej mapie i czy nie wyraźne komparator jest, musi być zgodny z równymi, czy to sortowych mapa jest do poprawnie zaimplementuj interfejs mapy. (Patrz Porównywalny lub Komparator dla dokładnej definicji zgodności z równymi.) Jest tak, ponieważ interfejs mapy jest zdefiniowany w kategoriach operacji równości, ale posortowana mapa wykonuje wszystkie kluczowe porównania przy użyciu metody compareTo (lub porównania), więc dwa klucze, które są uznawane za równe tą metodą, są z punktu widzenia posortowanej mapy równe. Zachowanie uporządkowanej mapy jest dobrze zdefiniowane, nawet jeśli jej uporządkowanie jest niespójne z równymi; po prostu nie przestrzega ogólnej umowy interfejsu Map.

Twoje porównanie nie jest zgodny z equals, dlatego widzisz wyniki, które naruszają umowę Map.

+1

* Lub * 'Comparator.comparingInt (Point :: l)' – Eugene

+0

@Eugene, ale to zajmuje więcej miejsca na ekranie. –

+0

@KlitosKyriacou to * zawsze * kłótnia? Robi się to właściwie, nie używając boksu/un-boxingu przez cały czas – Eugene

2
sortedSet.put(new Point(4,5,0),0); 
sortedSet.put(new Point(5,5,0),6); 

używać tych Zawieszanie połączenia za dostarczony komparator ((p1, p2)-> p1.l-p2.l) aby sprawdzić, czy dwa punkty są equal.

(new Point(4,5,0)).equals(new Point(5,5,0)) 

Wykorzystuje to wartość zastępowaną klasą Point.

Dlatego różnica ...