使用嵌套的HashMaps是不好的做法吗?

Shr*_*yas 8 java hashmap data-structures

让我解释一下我的情景.我有一些我需要维护的层次结构.在下面找到显示此层次结构的图像.我将在图像后解释.

   A
   |          +--> A1.1 ---> X
   |          | 
   +--> A1 ---+--> A1.2 ---> Y
   |          |
   |          .
   +--> A2    .
   .
   .
Run Code Online (Sandbox Code Playgroud)
  • AA1, A2...这是一个一对多的关系
  • A1A1.1, A1.2...这是一个一对多的关系
  • A1.1XA1.2Y它是一个一对一的关系.

最初我设计它的方式是使用多个HashMaps来维护它.但后来我很快意识到更新变得非常困难.

拥有多个HashMaps意味着我必须自己处理不同关系中的唯一性.例如,A1.1也可以存在于根节点内B.因此,我必须附加A,A1.1以便我可以确保唯一性.现在,如果我需要修改的值A,然后我在大麻烦,因为我已经使用了限定范围内的所有键AA_A1.1

现在我想我可以使用Nested HashMaps.所以代码变为:

HashMap<String, HashMap<String, HashMap<String, CustomObject>>> _worldsBiggestHash; 
Run Code Online (Sandbox Code Playgroud)

这种做法好吗?我确实有很多记账要做,因为我将使用嵌套哈希,但至少CRUD和唯一性问题处理自己.

如果这不合适,有人可以建议我可以使用另一个更好的结构吗?

Mar*_*o13 5

你显然想要树模型.该树不一定与TreeMap显式相关.诚然,我没有看到如何TreeMap帮助表示整个结构(尽管它可以在单个树节点中使用).

你可以创建一个这样的类

class Node 
{
    private final String name;
    private final Map<String, Node> children;
    private final CustomObject customObject;

    Node(String name, CustomObject customObject)
    {
        this.name = name;
        this.children = new LinkedHashMap<String, Node>();
        this.customObject = customObject;
    }

    String getName()
    {
        return name;
    }

    void addChild(Node child) 
    {
        children.put(child.getName(), child);
    }

    void removeChild(String name)
    {
        children.remove(name);
    }

    Node getChild(String name)
    {
        return children.get(name);
    }

    Set<Node> getChildren()
    {
        return Collections.unmodifiableSet(
            new LinkedHashSet<Node>(children.values()));
    }
Run Code Online (Sandbox Code Playgroud)

(只是快速草图)

然后你可以像这样构建层次结构

Node root = new Node("", null);
Node a1 = new Node("A1", null);
Node a2 = new Node("A2", null);
root.addChild(a1);
root.addChild(a2);

Node a11 = new Node("A11", x);
Node a12 = new Node("A12", y);
a1.addChild(a11);
a1.addChild(a12);
Run Code Online (Sandbox Code Playgroud)

这将允许您在层次结构中导航,并且维护关系将非常容易.

我并不完全理解你对"独特性"所说的话.在任何情况下,在这样的树中,每个节点由路径唯一地标识.您甚至可以创建一个实用工具方法

CustomObject c = root.find("A", "A1", "A11");
Run Code Online (Sandbox Code Playgroud)

通过节点名称序列快速访问对象.


旁白:正如已经指出的那样,深层嵌套的地图(或列表或集合)是值得怀疑的.但无论如何,你应该总是使用接口,比如

Map<String, Map<String, CustomObject>> maps;
Run Code Online (Sandbox Code Playgroud)

可能是对某些使用情况确定,但根据什么正是你想要的模型(特别是,当有另一层),这可能已经是不方便的.