【问题标题】:Java - multiple hashmaps pointing to the same keyJava - 指向同一个键的多个哈希图
【发布时间】:2017-08-10 08:26:57
【问题描述】:

我有多个包含 key=value 字符串对的文件。文件之间的键相同,但值不同。每个文件可以有 1000 多个这样的对。

我想将每个文件存储在一个单独的hashmap中,即map<KeyString, ValueString>,所以如果有五个文件,那么就会有五个hashmap。

为避免在每个哈希映射中重复键,是否可以让每个映射引用相同的键?请注意,一旦将键添加到地图中,它就不会被删除。

我考虑将第一个文件作为享元模式中的“基础”,这个基础将是键/值的内在集合。其他剩余的文件将是外部值集,但我不知道如何在不复制键的情况下将这些值关联回基本(内部)键?

我愿意接受更简单/更好的方法。

【问题讨论】:

  • 感谢您的建议。我决定使用字符串池,无论是使用 intern() 还是手动池(如果默认情况下 Java 已经在实习,则根本没有)。再次感谢。

标签: java hashmap


【解决方案1】:

我可以考虑一个更简单的方法。而不是让Map<String, String> 想到Map<String, List<String> 或直接从guava 获得MultiMap<String, String>

如果每个键都在每个文件中并且都有值,您可以将值存储在第 0 个索引的第一个文件、第一个索引的第二个文件等。

如果它不起作用,我推荐Collection<Map<String, String>,这样您就可以遍历您的Maps。然后,当您想为Maps 之一添加值时,请遍历所有keySets,如果其中一个包含该键,则只需放入从该keySet 返回的对象。

其他解决方案是拥有一个HashSet 已放置的密钥。这样会更有效率。

【讨论】:

    【解决方案2】:

    读入密钥后,您可以使用String.intern()。 调用时,它的作用是:

    • 如果字符串尚不存在,则将其添加到内部池中;
    • 如果它已经存在,则从池中返回等效的字符串。

    String#intern Javadoc

    【讨论】:

    • 不错的收获!不知道!
    • @kewne 请不要...如果出现问题,这将是调试的噩梦。通常intern 非常不鼓励
    • @Eugene 我同意intern 应该在特殊情况下使用,但似乎就是这样。为什么这里不合适?
    • @kewne 它不在这里,它可能在无处不在;此外,如果您真的想要一个实例 - 使用枚举(就像我在回答中所说的那样)。但是,如果您仍然想要这样 - 声明为私有静态最终文字会将其放入池中,而无需 intern
    • @Eugene 使用枚举/常量需要对 1000 个加号键中的每一个进行编码。从问题中不清楚 OP 实际上想要对键进行匹配,只是他想使用 flyweights。使用常量将常量放入池中;即使从文件中读取的字符串是等价的,它们本身也在池中。要获得相同的行为,您必须实现与intern 等效的逻辑。我仍然不清楚为什么 intern 在这里不合适以及它可能导致什么问题。
    【解决方案3】:

    首先,我看不到存储多个字符串键实例的问题。 5 HashMaps * 1000 个键是一个非常小的数字,你不应该有内存问题。

    也就是说,如果您仍想避免重复 Strings,您可以创建第一个 HashMap,然后为其他 HashMaps 创建完全相同的密钥。

    例如,假设map1 是第一个HashMap,并且已经填充了第一个文件的内容。

    你可以写这样的东西来填充第二个HashMap

    for (String key : map1.keySet()) {
        map2.put (key, someValue);
    } 
    

    当然,您必须为第一个映射的每个key 找到第二个映射的对应值。如果密钥在输入文件中的存储顺序不同,这可能需要一些初步的排序步骤。

    【讨论】:

    • Enum 作为关键...以防他真的想要那个
    【解决方案4】:

    也许您可以持有static Map<> 将您的键映射到唯一的Integers 并使用这些Integers 作为您映射的键?

    类似:

    class KeySharedMap<K,V> {
        // The next key to use. Using Atomics for the auto-increment.
        static final AtomicInteger next = new AtomicInteger(0);
        // Static mapping of keys to unique Integers.
        static final ConcurrentMap<Object,Integer> keys = new ConcurrentHashMap<>();
        // The map indexed by Integer from the `keys`.
        Map<Integer, V> map = new HashMap<>();
    
    
        public V get(Object key) {
            return map.get(keys.get(key));
        }
    
        public V put(Object key, V value) {
            // Associate a unique integer for each unique key.
            keys.computeIfAbsent(key,x -> next.getAndIncrement());
            // Put it in my map.
            return map.put(keys.get(key),value);
        }
    }
    

    是的,我知道这里没有使用 K,但我怀疑如果您希望实现 Map&lt;K,V&gt;,这将是必要的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-24
      • 1970-01-01
      • 2019-04-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多