Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用嵌套哈希映射是一种不好的做法吗?_Java_Data Structures_Hashmap - Fatal编程技术网

Java 使用嵌套哈希映射是一种不好的做法吗?

Java 使用嵌套哈希映射是一种不好的做法吗?,java,data-structures,hashmap,Java,Data Structures,Hashmap,让我解释一下我的情况。我需要维护一些层次结构。在下面找到显示此层次结构的图像。我会在图片之后解释 A | +--> A1.1 ---> X | | +--> A1 ---+--> A1.2 ---> Y | | | . +--> A2 . . . 从A到A1,A2…这是一种一对多的关系 从A1到A1.1、A1.2…这是一种一

让我解释一下我的情况。我需要维护一些层次结构。在下面找到显示此层次结构的图像。我会在图片之后解释

   A
   |          +--> A1.1 ---> X
   |          | 
   +--> A1 ---+--> A1.2 ---> Y
   |          |
   |          .
   +--> A2    .
   .
   .
  • A
    A1,A2…
    这是一种一对多的关系
  • A1
    A1.1、A1.2…
    这是一种一对多的关系
  • A1.1
    X
    A1.2
    Y
    这是一种一对一的关系
最初我设计它的方式是使用多个
HashMap
s来维护它。但后来我很快意识到更新变得非常困难

拥有多个
HashMap
s意味着我必须自己处理不同关系之间的唯一性。例如,
A1.1
也可以存在于根
B
节点中。因此,我必须将
A
附加到
A1.1
中,以确保唯一性。现在,如果我必须修改
A
的值,那么我就有大麻烦了,因为我用它将
A
中的所有键限定为
A_A1.1

现在我想我可以使用嵌套的
HashMaps
来实现这一点。因此,这方面的代码变成:

HashMap<String, HashMap<String, HashMap<String, CustomObject>>> _worldsBiggestHash; 
HashMap\u worldsBiggestHash;
这种做法行吗?我确实有很多簿记工作要做,因为我将使用嵌套哈希,但至少CRUD和唯一性问题会自行处理


如果这不好,有人能建议我使用另一个更好的结构吗

你的建议不可取

假设您的需求能够基于密钥在O(log(n))时间内获取项。 我建议采取以下措施之一,以更好地解决此问题:

  • 使用树映射,或者如果需要并发性,使用ConcurrentSkipListMap(这将是我解决问题的第一选择)
  • 有一个树集来包含键,还有一个单独的HashMap来映射键和值
  • 创建一个封装映射的类(即HashMap Decorator),该类将递归地处理唯一键检查(同样,第一种方法更可取)

  • 显然,您需要对树进行建模。此树不一定与
    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()));
        }
    
    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);
    
    这将允许您在层次结构中导航,并且维护关系将非常容易

    我没有完全理解你所说的“独特性”。在任何情况下,在这样的树中,每个节点都由路径唯一标识。您甚至可以创建一个实用方法,如

    CustomObject c = root.find("A", "A1", "A11");
    
    通过节点名称序列快速访问对象


    旁白:正如已经指出的,深度嵌套的映射(或列表或集合)是有问题的。但不管怎样,您应该始终使用接口,如

    Map<String, Map<String, CustomObject>> maps;
    
    地图;
    

    这对于某些用例来说是可以的,但取决于您想要建模的确切内容(特别是当有另一层时),这可能已经很不方便了。

    使用3个嵌套的
    HashMap
    s已经是一个糟糕设计的标志。。你应该考虑创建自己的类来隐藏嵌套的映射。使用一个封装了<代码>字符串和一个<代码> HashMap <代码>的类,然后使用另一个封装前一个的.Maloun我在它周围有一个类(单独的哈希表),但是就像我所说的更新变得昂贵一样。对吗?@ambigram_maker你能再解释一下吗?@shraya在什么意义上是昂贵的?跳过列表比哈希表有什么好处?哈希表不支持这里需要的树结构,而且哈希表同步实现线程安全的所有方法,这非常慢。此外,ConcurrentSkipListMap支持并发编辑,而无需抛出ConcurrentModificationException。你能再详细一点吗?谢谢。树形图是一个树形图,因此,默认情况下,它有一个树的层次结构。好的,但是我仍然不清楚在哪里可以维护层次结构
    a->A1
    B->B1
    。很抱歉,我对树木和大麻还不太熟悉哇,这太全面了。我会花点时间来理解这一点,然后再联系你。但看起来这可能会有所帮助。谢谢你,好心的先生。这就是我要找的。谢谢@Marco13。我从中了解了很多。