简体   繁体   English

在HashMaps中使用可变对象作为键

[英]Using mutable objects as keys in HashMaps

I have a digraph data structure which uses list representation( HashMap<Vertex, ArrayList<Vertex>> ); 我有一个使用列表表示的有向图数据结构( HashMap<Vertex, ArrayList<Vertex>> ); source vertex as the key and an ArrayList of destination vertices as the value. 源顶点作为键,目标顶点的ArrayList作为值。 A depth first search and dfs loop are used to traverse the graph to find the execution order of the vertices. 深度优先搜索和dfs循环用于遍历图以找到顶点的执行顺序。

The execution order is set as a label of a Vertex object by setLabel(int i) and only the String name field is used to generate hashcode . 通过setLabel(int i)将执行顺序设置为Vertex对象的标签,并且仅将String name字段用于生成hashcode

My problem is that after dfs is completed and when I iterate through the keys of the HashMap [ graph.keySet() ] , there are still few Vertices which are not labeled, But when I iterate though the explored set which is a HashSet<Vertex> , all the possible vertices are labeled(Accurately). 我的问题是在完成dfs之后,当我遍历HashMap [ graph.keySet() ]的键时, 仍然有一些顶点没有被标记,但是当我遍历所探索的集合(即HashSet<Vertex> ,所有可能的顶点都被标记(准确)。

What could possibly be happening here? 这里可能会发生什么? (I can only use the HashMap to retrieve the labels of the vertices) (我只能使用HashMap来检索顶点的标签)

Note: I believe this is relevant to using mutable objects as keys in HashMaps. 注意:我相信这与在HashMaps中使用可变对象作为键有关。 If not please correct me. 如果没有,请纠正我。

 /**
 * Recursive depth-first search     
 * @param graph HashMap<Vertex,ArrayList> (list representation)
 * @param start starting Vertex
 */
public void dfsR(HashMap<Vertex, ArrayList<Vertex>> graph, Vertex start) {
    this.explored.add(start); //a HashSet<Vertex>        

    ArrayList<Vertex> list = graph.get(start);
    if (list != null) {
        for (Vertex v : list) {
            if (!this.explored.contains(v)) {
                this.dfsR(graph, v);
            }
        }
    }
    /* First pass-Execution order */
    if (!this.secondPass) {
        start.setLabel(++this.label);
    }
}

 /**
 * Run DFS on every vertex of the Graph      
 * @param graph HashMap<Vertex,ArrayList<Vertex>> (list representation)
 */
private void dfsLoop(HashMap<Vertex, ArrayList> graph) {
    this.secondPass = false;
    this.explored.clear();        
    this.label = 0;
    for (Vertex vertex : graph.keySet()) {
        if (!this.explored.contains(vertex)) {
            this.dfsR(graph, vertex); /* Recursive dfs */                                
        }
    }
}

public class Vertex {

private final String name;
private int label;    

public Vertex(String name) {
    this.name = name;
    this.label = -1;
}

public Vertex(Integer name) {
    this.name = String.valueOf(name);
    this.label = -1;
}

public String getName() {
    return name;
}

/**
 * Value(Label) obtained from Topological Ordering  
 * @param label integer value of the relevant position
 */
public void setLabel(int label){
    this.label = label;
}

/** 
 * @return the Label obtained from the Topological ordering
 */
public int getLabel(){
    return this.label ;
}    

@Override
public String toString() {
    return name;
}

@Override
public boolean equals(Object o) {
    if(o == null){
        return false;
    }
    if (o instanceof Vertex) {
        Vertex v = (Vertex) o;
        return this.name.equals(v.getName());
    }
    return false;
}

@Override
public int hashCode() {
    int hash = 3;       
    hash = 89 * hash + this.name.hashCode();
    return hash;
}}

The problem is almost certainly related to the management of the secondPass variable, as that is what controls whether or not to set the label: 这个问题几乎可以肯定与secondPass变量的管理有关,因为这是控制是否设置标签的原因:

if (!this.secondPass) {
    start.setLabel(++this.label);
}

The code you provided does not show where this would be set to true. 您提供的代码未显示将其设置为true的位置。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM