2017-08-01 64 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. 

我重載了哈希碼,equals方法在類中。我認爲put方法應該使用equals方法來確定相同的對象是否退出。但它沒有按預期工作。TreeMap投入不按預期工作

我不確定爲什麼我的hashMap大小爲1.請讓我知道,如果我理解hashmap工作錯誤。幫我找出這段代碼中的錯誤?

+2

爲什麼你的平等檢查'p1.l - p2.l'? –

+0

爲什麼當它不是一個集合,而是一個地圖時,調用變量'sortedSet'? –

+0

@MuratK:這不是一個平等檢查 - 這是一個排序。 –

回答

5

TreeMap只使用提供的Comparator(或可用的自然順序)來確定相等性,因此equalshashCode沒有區別。

對於您的情況,兩個Point s都具有相同的l值,因此根據您的Comparator將它們視爲相同。

您可以通過修改Comparator確定您的鍵的順序(和平等)時採取的所有屬性(lxy)考慮在內。

11

您的TreeMap正在比較Pointl部分(無論這是什麼意思)。這就是你的這部分代碼的作用:

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

您創建具有相同的l值(0)2點所以他們認爲等於......所以put第二次調用替換現有條目。 TreeMap根本不使用equalshashCode

documentation

注意,排序由一棵樹映射維護,像任何排序的映射,無論是否提供了明確的比較器,如果此映射是必須與equals一致正確實現Map接口。 (請參閱Comparable或Comparator以獲得與equals一致的精確定義)。這是因爲Map接口是根據equals操作定義的,但有序映射使用其compareTo(或compare)方法執行所有關鍵比較,因此兩個從排序映射的角度來看,這種方法認爲相同的鍵是相等的。即使排序與等號不一致,排序映射的行爲也是很好定義的;它只是不服從Map接口的總體合同。

你比較符合equals,這就是爲什麼你看到這違反了合同Map結果。

+1

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

+0

@Eugene確實,但佔用了更多的屏幕空間。 –

+0

@KlitosKyriacou是*永遠*爭論?這是做正確的事情,通過不總是使用拳擊/取消拳擊 – Eugene

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

這些認沽電話的使用提供比較((p1, p2)-> p1.l-p2.l)來檢查是否有兩點是equal

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

這使用在Point類中等於覆蓋。

因此,區別..