我有一个ConcurrentHashMap
,它从不同的线程调用以将值放入其中。我必须插入空值,但ConcurrentHashMap
不允许null
值。有没有办法在Java中执行此操作或替代选项?
答案 0 :(得分:5)
而不是使用没有语义含义且通常被认为是antipattern的null
,而不是#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);
}
}