简体   繁体   English

在Java中使用多级HashMap的最佳实践

[英]Best Practices for Using Multi Level HashMap in Java

We have a situation where we are ending up using multi-level hash maps; 我们有一种情况,我们最终使用多级哈希映射; that is, a hash map inside of a hash map, three or four levels deep. 也就是说,哈希映射内部的哈希映射,深度为三层或四层。

Instinctively this felt wrong somewhere. 本能地,这在某个地方感觉不对。 I have read posts here that talks about how to iterate/use a multi-level hash map, but hardly any of them say what is the best practice for this. 我在这里阅读了有关如何迭代/使用多级哈希映射的帖子,但几乎没有人说这是什么最好的做法。

Why are multi level hash maps bad, and what would be the better design, if any? 为什么多级哈希映射不好,哪个更好的设计,如果有的话?

Here is the sample design of multi-level hash maps that we have: 以下是我们拥有的多级哈希映射的示例设计:

Map<String, Object1> map1;

class Object1 {
    String version;
    Map<String,Object2> map2;
}

class Object2 {
    Map<String,List<Object3>> map4;
    Map<String,String> map5;
}

As long as they're properly abstracted, it's not that big of a deal, but you lead yourself down some nasty rabbit holes in terms of readability. 只要它们被正确抽象,它就不是那么重要,但是你在可读性方面让自己陷入了一些令人讨厌的兔子洞。 Without abstraction, maintaining this becomes a nightmare that no developer would wish on another. 没有抽象,维持这一点就成了开发人员不希望另一个人做的噩梦

Essentially, what you're creating is a table of sorts; 从本质上讲,你正在创建的是一个表格; the first key is the primary key to gain access to further columns. 第一个密钥是访问更多列的主键。 On a simple one, two, or three-level design, this isn't terrible; 在简单的一,二或三级设计中,这并不可怕; you need three keys to get a single value. 你需要三个键来获得一个值。 Provided that there's a convenient way to access it, like the below, it's not a terrible idea (although there are far better out there). 如果有一种方便的方式来访问它,如下所示,这并不是一个可怕的想法(虽然那里有更好的)。

public interface Table<K1, K2, K3, V> {
    V get(K1 key1, K2 key2, K3 key3);
}

...However, it all depends on what you're actually doing with that data structure. ......然而,这一切都取决于你实际上与数据结构什么。 If you find yourself attempting to iterate intermediate keys for values (that is, you're looking at Key 3 for the collection of all values between it and Key 5), you've got to rethink your business logic at that point. 如果您发现自己试图迭代值的中间键(也就是说,您正在查看键3以获取它与键5之间的所有值的集合),那么您必须重新考虑您的业务逻辑。 The data structure provided isn't flexible enough to handle all cases; 提供的数据结构不够灵活,无法处理所有情况; more or less, it's used for simplistic indexing based on a set of values. 或多或少,它用于基于一组值的简化索引。

Alternatively, one could look into a Guava Table , as that does the same sort of thing, with a better interface to it (something like the one I have above). 或者,可以看一下Guava Table ,因为它做同样的事情,有一个更好的界面(类似于我上面的那个)。

Multi-level HashMaps are not necessarily bad, it depends on your algorithm. 多级HashMaps不一定是坏的,这取决于您的算法。 The bad thing is that it's more difficult to manage. 糟糕的是管理起来比较困难。 Consider using interfaces (something like repository) for HasMap values, this may make your design cleaner. 考虑使用HasMap值的接口(类似于存储库),这可能会使您的设计更清晰。 Other option is to use composite keys in a HashMap. 其他选项是在HashMap中使用复合键。

I think doing HashMap within HashMap is bad practice, because in order to extend your HashMap to go deeper, will cost you both time and money. 我觉得做HashMapHashMap是不好的做法,因为为了延长您的HashMap深究下去,会花费你的时间和金钱。 Going from 3 level depth Map to 5 level depth Map , you would essentially have to re-code your Class. 3级深度Map5级深度Map ,您基本上必须重新编码您的类。 Which will put a lot of technical debt when it comes to maintaining this program. 在维护这个项目时,这会带来很多技术债务。

Declare the Initial Map somewhere 在某处声明初始地图

Map<String, MyHashedObject> HashKVP = new HashMap<String, MyHashedObject>();

Then have an Object to store additional maps. 然后有一个Object来存储其他地图。

class MyHashedObject {

    private Map<String, MyHashedObject> InternalKvp;

    public MyHashedObject() {
        this.InternalKvp = new HashMap<String, MyHashedObject>();
    }

    /*
    * Get the next level of our MyHashedObject object
    * @param HashKey
    * @return MyHashedObject result
    */
    public MyHashedObject findHashedObject(String HashKey) {
        MyHashedObject result = null;
        if(this.InternalKvp.containsKey(HashKey)) {
            result = this.InternalKvp.get(HashKey);
        }
        return result;
    }




}

This way, you can easily extend more levels to your HashMap by simply dumping more Objects into the InternalKvp . 这样,只需将更多对象转储到InternalKvp ,就可以轻松地将更多级别扩展到HashMap

This just a very basic example, but you can add more properties to the MyHashedObject (such as depth , parent_object etc). 这只是一个非常基本的示例,但您可以向MyHashedObject添加更多属性(例如depthparent_object等)。 You could do something like Small-world network , to track the depth of each object. 您可以执行类似小世界网络的操作 ,以跟踪每个对象的depth

This could also be done better, using a RedBlackTree or AVLTree to make it easier to traverse through the Maps . 使用RedBlackTreeAVLTree可以更好地完成此操作,以便更轻松地遍历Maps

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

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