如何将空值添加到ConcurrentHashMap

时间:2015-07-23 02:23:27

标签: java collections hashmap concurrenthashmap

我有一个ConcurrentHashMap,它从不同的线程调用以将值放入其中。我必须插入空值,但ConcurrentHashMap不允许null值。有没有办法在Java中执行此操作或替代选项?

2 个答案:

答案 0 :(得分:5)

而不是使用没有语义含义且通常被认为是antipatternnull,而不是#34;缺席"这个概念是一种反映你意图的具体类型,并迫使呼叫者正确地解释它。

一个常见的解决方案是使用Optional(对于Java 8之前的版本,使用Guava' s Optional)来表示缺少值。

因此,您的地图的类型为ConcurrentHashMap<Key, Optional<Value>>

另一种选择是通过null更直接地表示您在地图中存储的类型中意味着什么意思,例如如果null应该表示&#34;这曾经存在,但不再是&#34;你可以像这样创建一个类结构:

public abstract class Resource {
  public abstract void doSomething();
  public abstract ClosedResource close();
}

public class ActiveResource extends Resource {
  public void doSomething() { ... }
  public ClosedResource close() { ... }
}

public class ClosedResource extends Resource {
  public void doSomething() { /* nothing to do */ }
  public ClosedResource close() { return this; }
}

然后只需ConcurrentHashMap<Key, Resource>。两种方法都有利弊,具体取决于您的确切需求,但两者都比在地图中放置null值更客观。

如果您无法为null创建明确的语义含义,那么您也可以简单地避免添加null - 这与仅仅缺席(如上所述,只需在地图中使用缺席来表达你关心的内容,而不是区分缺席和现在但null个案例。

答案 1 :(得分:3)

一个简单的答案是“如果值为null,请不要尝试添加它”。

另一个答案是从.NET获取一个页面并引入一个Nullable。您的值将是Nullable的一个实例。

public class Nullable<T> {
    private final T obj;
    public Nullable(T t) {
        obj = t;
    }

    public T get() {
        return obj
    }
}

您可以使用null值成功创建Nullable实例。您可以使用get()获取值。

---这是答案的旧版本---

首先,为什么需要放一个空键?这似乎是你设计中的一个问题。

话虽这么说,你可以使用一个替换为null的替身。说你的钥匙是KeyLikeThing。通常,KeyLikeThing具有影响其散列和等于属性的属性。您可以在您的世界中将KeyLikeThing的实例设为null。当您的客户端想要放置null时,它会使用KeyLikeThing的实例。

public class KeyLikeThing {
    public static final KeyLikeThing NULL = new KeyLikeThing();

    // Other KeyLikeThing related stuff.
}

public class Storage<T> {
    private ConcurrentHashMap m = new ConcurrentHashMap();

    public T put(KeyLikeThing k, T val) {
        KeyLikeThing kl = k == null ? KeyLikeThing.NULL : k;
        return m.put(kl, val);
    }
}