2013-05-16 72 views
3

我正在Java中實現A *算法,並且我使用TreeSet作爲保持打開列表排序的簡單方法。如果你不熟悉A *,它基本上是一條從A到B的最短路徑的函數,而打開的列表是根據它們與B的接近度排序的節點列表(在我的例子中爲)。TreeSet add()返回false

我的目標實現了compareTo()功能分類,像這樣:

@Override 
public int compareTo(Tile b) 
{ 
    return (this.f< b.f) ? -1 : (this.f> b.f) ? 1 : 0; 
} 

我的問題是當我嘗試一些瓷磚添加到開放列表 - TreeSet中似乎使用compareTo()檢查的對象是已經存在的,而不是equals()。由於有可能兩個不同的具有相同的值f,TreeSet認爲該對象已經存在於列表中,並且不會添加它。

按照文檔(或者至少,我是如何讀它),它應該使用equals

「指定的元素添加到這個集合,如果它是不存在更正式,加如果該集合不包含元素e2,使得(e == null?e2 == null:e.equals(e2))。 (重點是我的)。

如何在調用add()或和compareTo()進行排序時如何讓TreeSet使用equals()?有關信息,我的Tile類不覆蓋equals()函數,所以它應該得到默認return a == b

如果我想要做的事對TreeSet來說是不可能的,那麼我應該使用什麼合適的集合呢?

回答

5

這是預期的行爲,因爲按照TreeSet的文檔:

注意,由一組(無論是否提供了明確的比較器)保持的順序必須與equals一致,如果它是正確實現Set界面。 (請參閱Comparable或Comparator以獲得與equals一致的精確定義。)這是因爲Set接口是根據equals操作定義的,但TreeSet實例使用其compareTo(或compare)方法執行所有元素比較,所以兩個從這個方法看,被這個方法認爲是相等的元素是相等的。即使排序與等號不一致,集合的行爲也是明確定義的;它只是不服從Set接口的總體合同。

你不能得到TreeSet調用addcontains時使用equals。您最好的選擇是通過比較f財產以及equals關心的任何其他財產,使您的compareTo方法與equals一致。

+0

請TreeSet中添加#java的方法-doc,它表示#equals被使用,實際上它不是 – hoaz

+1

TreeSet文檔指出,如果比較器與等號不一致,那麼所有這些賭注都是關閉的。無論您對文檔有何解釋,您都已經證明了這一點。 –

+0

你可以檢查實現,它從不調用等於 – hoaz

0

我希望下面的例子可以幫助SO用戶。我有類似的情況,我所處理的方式是除了價值之外還使用id。就我而言,價值是指一個頻率。

請注意'paddedText'的使用 - 如果您進行字符串比較,則這很重要3> 11。

public int compareTo(Object o) { 
 
\t \t String oText= o.getValue()+""; 
 
\t \t oText = String.format("%20s",oText).replace(' ', '0')+o.getName(); 
 
\t \t paddedText = this.value +""; 
 
\t \t paddedText=String.format("%20s",paddedText).replace(' ', '0') + this.name; 
 
\t   return oText.compareTo(paddedText); 
 
\t }

0

的答案已經在這裏促使我創建這個。我會把它留在這裏,因爲似乎仍然只有解決方案的要點。

@Override 
    public int compare(TileState lhs, TileState rhs) { 
     int compare = (lhs.getTaxicab + lhs.mMoves.size()) 
       - (rhs.getTaxicab + rhs.mMoves.size()); 
     if (compare == 0 && !lhs.equals(rhs)) return 1; 
     return compare; 
    } 

你只需要擔心,當你比較方法返回0

如果是這樣的話,等於將返回false,然後返回以外的任何其他0