【问题标题】:Qt-like multivalue map for Java?Java的类似Qt的多值映射?
【发布时间】:2012-11-03 23:12:04
【问题描述】:

是否有一个现有的开源Map java 实现,这将是一个普通的键值映射,但支持每个键的多个值?我发现的多映射实现似乎将键与集合相关联,这并没有完全消除它,因为我需要一个替换现有代码的插件。

我感觉到有些人在说“你不能那样做”,所以这里有一个示例,说明它在广泛使用的框架 Qt 中的行为方式。这是QMap class 的文档摘录:

如果地图不包含键为 key 的项目,则该函数返回一个 默认构造的值。如果有多个 key 项 map,返回最近插入的值。

我的需求非常有限,所以目前我正在使用下面的 hack,这已经足够了,因为没有删除,每个键的许多值都是例外,并且重复键有点损坏不是问题:

public static <V, V2 extends V> String mapMultiPut(
        Map<String, V> map, 
        String key, 
        V2 value) {
    int count = 0;
    String tmpKey = key;
    while (map.containsKey(tmpKey)) {
        ++count;
        tmpKey = key + '_' + count;
    }
    map.put(tmpKey, value);
    return tmpKey;
}

但我想要一个更好的解决方案,如果有的话......

【问题讨论】:

  • @MarkRotteveel 这个问题没有“必须直接替换法线贴图”方面,这是我问题的重点。
  • 一个普通的 Map.put 用新的值覆盖之前的值。你缺少什么功能?
  • @Score_Under 这个问题已经有半年的历史了,我不记得确切的用例了,但是看看我的老问题,缺少的功能是/相当于QMap::insertMulti...

标签: java collections map multimap


【解决方案1】:

你可以使用 ListMultimap 和

Iterables.getLast(listMultiMap.get(key), defaultValue(key))

您可以在其中定义自己的 defaultValue 方法。

这假设你的类中实际上不需要Map 接口。

如果你真的想要Map,你可以试试这个

public abstract class QtMap<K, V> extends ForwardingMap<K, V>
{
    private final ListMultimap<K, V> listMultimap = ArrayListMultimap.create();

    final Map<K, V> delegate = Maps.<K, Collection<V>, V> transformEntries(listMultimap.asMap(), new EntryTransformer<K, Collection<V>, V>()
    {

        @Override
        public V transformEntry(K key, Collection<V> value)
        {
            return Iterables.getLast(value, defaultValue(key));
        }

    });

    @Override
    protected Map<K, V> delegate()
    {
        return delegate;
    }

    @Override
    public V put(K key, V value)
    {
        listMultimap.put(key, value);
        return null;
    }

    @Override
    public void putAll(Map<? extends K, ? extends V> map)
    {
        for (Map.Entry<? extends K, ? extends V> entry : map.entrySet())
        {
            put(entry.getKey(), entry.getValue());
        }
    }

    @Override
    public V get(Object key)
    {
        return listMultimap.containsKey(key) ? delegate.get(key) : defaultValue(key);
    }

    protected abstract V defaultValue(Object key);

}

虽然只是粗略的测试

【讨论】:

    【解决方案2】:

    Guava 库有一个 Multimap,它允许每个键有多个值 :)

    【讨论】:

    • 正如我在问题中所说:“我发现的多图实现似乎将键与集合相关联,这并不能完全消除它。”
    • 您是否阅读过 OP 链接的文档?预期的行为是地图返回最近插入的单个值,而不是值的集合。
    猜你喜欢
    • 2015-08-22
    • 1970-01-01
    • 2012-03-04
    • 2014-05-07
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多