3

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

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

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

我的需求非常有限,所以目前我正在使用下面的 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;
}

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

4

2 回答 2

0

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

于 2012-11-15T11:09:49.500 回答
0

您可以使用 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);

}

虽然只是粗略地测试过

于 2012-11-15T14:03:24.790 回答