2013-03-26 79 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