java 自定义对象比较器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15635714/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 20:20:35  来源:igfitidea点击:

Custom object comparator

javacollectionstreeset

提问by Whizzil

I will try to get right to the point.

我会尽量切入正题。

I am having my custom Node objects, which have attribute Cost. I would want to sort those Node objects in ascending order by their attribute Cost.

我有我的自定义节点对象,它具有属性成本。我想按属性成本按升序对这些 Node 对象进行排序。

I was able to do so using PriorityQueue<Node> = new PriorityQueue<Node>(10000, new NodeComparator());, but that way worked too slow for me, and now I am looking to do the same thing, only using TreeSet. Anyways, if my constructor looks like this TreeSet<Node> = new TreeSet<Node>(new NodeComparator());, the program seems to skip vast amount of Node objects, seemingly treating them as they are the same. Which they are not. I am assuming there might be some hashCode issues about, but I am not sure, and I don't know how to resolve it at this moment.

我可以使用PriorityQueue<Node> = new PriorityQueue<Node>(10000, new NodeComparator());,但这种方式对我来说太慢了,现在我想做同样的事情,只使用 TreeSet。无论如何,如果我的构造函数看起来像这样TreeSet<Node> = new TreeSet<Node>(new NodeComparator());,程序似乎会跳过大量 Node 对象,似乎将它们视为相同的对象。他们不是。我假设可能存在一些 hashCode 问题,但我不确定,目前我不知道如何解决。

To be concise, I just want my Nodes in TreeSet to be ordered in ascending way by Cost attribute. Here is my NodeComparator class:

简而言之,我只希望 TreeSet 中的节点按成本属性升序排列。这是我的 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;
    }

}

And here is my Node class:

这是我的 Node 类:

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;
    }
}

I will provide you with my State class aswell.

我也会为您提供我的 State 课程。

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;
    }
}

回答by Pshemo

TreeSetuses TreeMapto store values. Your problem is that TreeMapinstead equalsuses result of comparatorto check if element is already in map. Because of that you need to include state of steatefield in comparemethod like

TreeSet使用TreeMap存储值。你的问题是,TreeMap而不是equals使用比较结果来检查元素已经在地图中。因此,您需要steatecompare方法中包含字段状态,例如

@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);
}

回答by SudoRahul

Setby default eliminates duplicates. You need to override your equals()& hashCode()in your Nodeclass.

Set默认情况下消除重复项。你需要在你的班级中覆盖你的equals()& 。hashCode()Node