Java 在树集中交换密钥?
假设我有这个班:Java 在树集中交换密钥?,java,hashset,treeset,Java,Hashset,Treeset,假设我有这个班: public class Node implements Comparable<Node>{ public float key; public TreeSet<Node> neighbors; public Node{ //fill neighbors somehow } @Override public int compareTo(Node n) { if(this.key == n.key)
public class Node implements Comparable<Node>{
public float key;
public TreeSet<Node> neighbors;
public Node{
//fill neighbors somehow
}
@Override
public int compareTo(Node n) {
if(this.key == n.key)
return 0;
else if(this.key > n.key)
return 1;
else
return -1;
}
}
请注意,此方法仅更改两个节点键,仅此而已
这样做会“破坏”结构,还是一切都会继续正常工作
如果这破坏了结构,那么这个简单的解决方案呢:
//swap nodes keys
void swapKeys(Node a, Node b){
a.remove(b);
b.remove(a);
float ak = a.key;
a.key = b.key;
b.key = ak;
a.add(b);
b.add(a);
}
从文件中:
请注意,由集合维护的顺序(无论是否为显式
如果提供比较器,则必须与equals一致
正确实现Set接口
您的节点
类“可比
实现与等于
不一致。(compareTo
可以为两个不相等的节点
实例返回0
)
这本身使您的节点
类不适合作为树集
的元素
即使是提议的解决办法也不够
您可能会试图通过基于节点中包含的值实现equals()
(和hashCode()
)来解决此问题。但没有用,因为这会违反通用接口文档上的警告:
注意:如果将可变对象用作集合,则必须非常小心
元素。如果
对象的更改方式会影响equals比较,而
对象是集合中的一个元素。这是一个特例
禁止是指不允许集合包含自身
作为一个元素
因此,添加equals和hashCode仍然不够:您的实例也必须是不可变的
然而,最简单的解决方案似乎是完全放弃
可比
接口,不实现equals
和hashCode
,只使用HashSet
而不是TreeSet
。在这种情况下,您可以更改节点的内容,而不会影响邻居集的正常运行。这将破坏结构。键应该是不可变的。Hashcode作为键添加后无法更改。@PiotrGwiazda感谢您的回答。那么我刚才发布的解决方案呢?@JonnyHenly在您发布评论时进行了编辑。为什么要交换节点的键并改变结构,而您只需交换它们的值而不改变结构?一个节点将有多少个邻居?也许你可以只使用一个列表而不是一套。谢谢你的评论。你是说我也必须实现equals
吗?HashSet
不幸的是,这不是一个选项,因为我经常使用tailSet
和headSet
来计算topK,正如前面解释的那样,你必须使用不可变节点。这将需要在图形中替换它们,而不是更改它们的内容。或者使用HashSet
,在算法中本地使用比较器创建一个TreeSet
,以查找k个最近的节点。
//swap nodes keys
void swapKeys(Node a, Node b){
a.remove(b);
b.remove(a);
float ak = a.key;
a.key = b.key;
b.key = ak;
a.add(b);
b.add(a);
}