是否存在强制最终密钥的Java Map实现?

Ofe*_*rBr 16 java map

我需要一个Map,一旦一个键获得一个值,任何额外的尝试将值放在同一个键上将抛出异常.

例如:

map.put("John", 3); //OK
map.put("John", 7); // throws some exception
map.put("John", 11); // throws some exception
Run Code Online (Sandbox Code Playgroud)

当然,我可以在我自己实现这个(例如,通过扩展HashMap,或每次调用到周围putif map.contains(key)),但我更喜欢使用一些现成的,保持我的代码清洁.

有人知道这样的实施吗?

fge*_*fge 13

JDK中没有这样的实现.这里你最好的选择是使用组合:

public final class CustomMap<K, V>
    implements Map<K, V>
{
    private final Map<K, V> delegate;

    public CustomMap(final Map<K, V> delegate)
    {
        this.delegate = delegate;
    }

    @Override
    public V put(final K key, final V value)
    {
        // Can't use the return value of delegate.put(), since some implementations
        // allow null values; so checking delegate.put() == null doesn't work
        if (delegate.containsKey(key))
            throw new IllegalArgumentException("duplicate key: " + key);
        return delegate.put(key, value);
    }

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

    // delegate all other methods
}
Run Code Online (Sandbox Code Playgroud)

否则,正如其他人建议的那样,如果你使用Guava,请使用ForwardingMap; 这基本上是上述代码的通用版本.

事实上,确实使用番石榴.


其他说明:你不能只// throws some exception在这里; Map.put()不声明抛出任何异常,所以你唯一的选择就是在这里抛出一个未经检查的异常.

  • 如果您只在应用程序中使用它,则应创建自己的界面以反映更改的合同.如果你需要它传递给其他代码(库等)你可能不应该这样做或者非常非常小心地考虑后果. (2认同)
  • 而对于上帝的爱,在Exception中加入一些东西告诉下一个人试试捕获链的确切值是重复的.:-) (2认同)