我知道有几十个与此类似的问题,但我无法找到我的具体问题的答案。对不起,如果我错过了 - 请告诉我在哪里看它是否存在!
这个问题对我来说似乎很常见:我需要一个按对象的某些属性排序的对象列表,并且只有列表中的每个对象一次。具体来说,我正在实现A *路径查找,需要按节点的F值排序的打开列表。
我尝试使用带有比较器的TreeSet,比较两个节点的f值,如下所示:
public class NodeFComparator implements Comparator<Node> {
@Override
public int compare(Node arg0, Node arg1) {
return (arg0.getF() - arg1.getF());
}
}
Class Node看起来像这样:
public class Node {
PathableMap parentmap;
Point coord; // coordinates on the map
private Node parent; // parent node: used by astar to backtrace shortest path
(etc etc)
/*
* F-value of a node is the sum of the distance from start + distance to target.
* The nodes are searched in the order of that value.
*/
public int getF() {
return getG() + getH();
}
@Override
public int hashCode() {
final int prime = 65537;
return prime * coord.x + coord.y;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Node other = (Node) obj;
if (coord == null) {
if (other.coord != null)
return false;
} else if (!coord.equals(other.coord))
return false;
return true;
}
}
这个解决方案的问题似乎是,如果两个不同的节点具有相同的f值(一直发生),换句话说比较器返回0,TreeSet似乎将其视为Node1 == Node2和不会将第二个节点添加到列表中或做一些其他奇怪的事情,因为我的openlist错过了应该存在的节点。
因此,我能想到使用现有类执行此操作的唯一方法是使用简单的ArrayList,并在每次向其添加节点时对其进行排序。
Java或Apache Commons中是否真的没有集合类:
答案 0 :(得分:3)
如果您想要比较相等的元素(在这种情况下,具有相同的f值),请不要使用集合。 A *算法通常是针对优先级队列定义的,从Java 5开始,Java集合API中提供了PriorityQueue
实现:
import java.util.PriorityQueue;
. . .
PriorityQueue nodes = new PriorityQueue<Node>(new NodeFComparator());
答案 1 :(得分:2)
你是对的,你可以使用ArrayList而不是TreeSet,因为它不会删除重复的项目(根据你传递它的比较器)。
您可以将节点添加到ArrayList,当您准备好对其进行排序时,从Collections类调用该方法,
Collections.sort(myList, myComparator)
答案 2 :(得分:2)
稍微改变你的比较器:
public class NodeFComparator implements Comparator<Node> {
@Override
public int compare(Node arg0, Node arg1) {
int result = arg0.getF() - arg1.getF();
if (result == 0)
return arg0.hashCode() - arg1.hashCode();
return result;
}
}
这将为具有不同f值的节点返回正确的结果,并且当节点具有相同的f值时,它们将通过其哈希码进行比较。您可以使用除哈希代码之外的任何其他唯一属性,但我选择哈希代码,因为它们几乎是唯一的,并且每个对象都有它们。
答案 3 :(得分:0)
如果compare方法与equals实现不一致,那么您必须小心使用哪些集合类。 TreeSet在这里不是一个好选择。另一种方法是查看Guava库https://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap
中的Multimap实现