2013-03-26 82 views
2

我會嘗試着正確的點。自定義對象比較器

我有我的自定義節點對象,它具有屬性Cost。我想按這些Node對象的屬性Cost升序排序。

我能夠這樣做使用PriorityQueue<Node> = new PriorityQueue<Node>(10000, new NodeComparator());,但這種方式對我來說太慢了,現在我正在尋找做同樣的事情,只使用TreeSet。 無論如何,如果我的構造函數看起來像這樣TreeSet<Node> = new TreeSet<Node>(new NodeComparator());,程序似乎會跳過大量的Node對象,看起來像對待它們一樣。他們不是。我假設可能會有一些hashCode問題,但我不確定,現在我不知道如何解決它。

爲了簡潔起見,我只是希望TreeSet中的節點按Cost屬性以升序方式排序。 這裏是我NodeComparator類:

public class NodeComparator implements Comparator<Node> { 

    @Override 
    public int compare(Node n1, Node n2) { 
     // TODO Auto-generated method stub 
     if(n1.cost > n2.cost) return 1; 
     else if(n1.cost < n2.cost) return -1; 
     else return 0; 
    } 

} 

這裏是我的節點類:

public class Node{ 

    public State state; 
    public int cost; 

    public Node(State s, int Cost){ 
     this.state = s; 
     this.cost = Cost; 
    } 

    public State getState(){ 

     return this.state; 
    } 

    public int getCost(){ 
     return this.cost; 
    } 
} 

我將爲您提供我的國家類以及。

public class State { 

    public int lamp; 

    public ArrayList<Integer> left; 


    public State(ArrayList<Integer> Left, int Lamp){ 
     lamp = Lamp; 
     left = Left; 
    } 

    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + lamp; 
     result = prime * result + ((left == null) ? 0 : left.hashCode()); 
     return result; 
    } 


    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     State other = (State) obj; 
     if (lamp != other.lamp) 
      return false; 
     if (left == null) { 
      if (other.left != null) 
       return false; 
     } else if (!left.equals(other.left)) 
      return false; 
     return true; 
    } 
} 
+2

'Set'默認 - 消除重複。你需要在你的'Node'類中覆蓋你的'equals()'''hashCode()'。 – SudoRahul 2013-03-26 11:21:41

+0

@ R.J:您應該將其作爲答案發布。 – Keppil 2013-03-26 11:23:48

+0

@Keppil - 完成! – SudoRahul 2013-03-26 11:25:34

回答

5

TreeSetuses TreeMap至​​。你的問題是TreeMap而不是equalsuses result of comparator檢查元素是否已經在地圖上。因爲你需要在compare方法steate場的狀態就像

@Override 
public int compare(Node n1, Node n2) { 
    // TODO Auto-generated method stub 
    if(n1.cost > n2.cost) return 1; 
    else if(n1.cost < n2.cost) return -1; 
    else return (n1.equals(n2)? 0 : 1); 
} 
+1

最後一個'1'應該像'(n1.hashCode() - n2.hashCode())' – 2013-03-26 11:47:37

+0

是的,你是對的。它以這種方式工作,但它並不能真正解決我最初的速度問題,因爲即使使用PriorityQueue,速度也降低了30%。 對此有何建議? 也許更好地實現NodeComparator(例如,以某種方式比較散列值)並結合TreeMap將會給出正確的結果。 – Whizzil 2013-03-26 11:52:11

+0

@Whizzil對不起,不知道如何改善它。 – Pshemo 2013-03-26 12:12:19

1

Set默認消除重複。您需要覆蓋您的Node課程中的equals() & hashCode()

+0

我試過,但問題仍然存在。 這樣,它只能經過620個節點,而使用PriorityQueue則會經過136000個節點。不知道爲什麼。 而且我已經在我的State類中覆蓋了equals()nad hashCode(),這也可以做到。 – Whizzil 2013-03-26 11:36:39