Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add null values to ConcurrentHashMap

I have a ConcurrentHashMap which is called from different threads to put values in it. I have to insert null values, but ConcurrentHashMap doesn't allow null values. Is there a way to do that or an alternate option to do this in Java?

like image 360
Khawar Ali Avatar asked Jul 23 '15 02:07

Khawar Ali


2 Answers

Rather than using null, which has no semantic meaning and is generally considered an antipattern, represent this "absent" notion as a concrete type that reflects your intent and forces callers to account for it properly.

A common solution is to use Optional (for pre-Java 8, use Guava's Optional) to represent the absence of a value.

So your map would have a type ConcurrentHashMap<Key, Optional<Value>>.


Another option is to represent whatever you intend to mean by null more directly in the type you're storing in the map, e.g. if null is supposed to mean "this used to exist, but no longer" you might create a class structure like so:

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; }
}

And then simply have a ConcurrentHashMap<Key, Resource>. There are pros and cons to both approaches depending on your exact needs, but both are objectively better than putting null values in your map.


You might also simply be able to avoid adding nulls at all - if you can't create a clear semantic meaning for null that's different from simply being absent (as suggested above), just use absence in the map to convey what you care about, rather than distinguishing between the absent and present-but-null cases.

like image 196
dimo414 Avatar answered Oct 27 '22 06:10

dimo414


One simple answer is "If the value is null, don't try to add it".

Another answer is to take a page from .NET and introduce a Nullable. Your values would be an instance of Nullable.

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

    public T get() {
        return obj
    }
}

You can successfully make instances of Nullable with a null value. You can get the value out with get().

--- This is the old version of the answer ---

First, why would you need to put a null key? That would seem like an issue in your design.

That being said, you could use a stand-in object for null. Say your key is KeyLikeThing. Normally a KeyLikeThing has attributes which affect its hash and equals properties. You can have an instance of KeyLikeThing is null in your world. When ever your client wants to put a null, it uses the instance of 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);
    }
}
like image 33
Virmundi Avatar answered Oct 27 '22 06:10

Virmundi