2015-07-23 6 views
3

У меня есть ConcurrentHashMap, который вызывается из разных потоков, чтобы поместить в него значения. Мне нужно вставить нулевые значения, но ConcurrentHashMap не разрешает значения null. Есть ли способ сделать это или альтернативный вариант сделать это в Java?Как добавить нулевые значения в ConcurrentHashMap

+3

Зачем вам это нужно? Дайте нам прецедент. –

+0

Возможно дублирование http://stackoverflow.com/questions/5699794/concurrenthashmap-alternative-with-null-key-capability – gastonmancini

+0

Вместо этого вы можете использовать объект, который является вашим «нулем». –

ответ

2

Один простой ответ: «Если значение равно null, не пытайтесь его добавить».

Другой ответ - взять страницу с .NET и ввести Nullable. Ваши значения будут экземпляром Nullable.

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

    public T get() { 
     return obj 
    } 
} 

Вы можете успешно сделать экземпляры Nullable с нулевым значением. Вы можете получить значение с помощью get().

--- Это старая версия ответа ---

Во-первых, почему бы вам нужно поставить пустой ключ? Это похоже на проблему в вашем дизайне.

При этом вы можете использовать объект stand-in для null. Скажем, ваш ключ - KeyLikeThing. Обычно KeyLikeThing имеет атрибуты, которые влияют на его хэш и равны свойствам. У вас может быть экземпляр KeyLikeThing в вашем мире нулевым. Когда ваш клиент хочет поместить нуль, он использует экземпляр 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); 
    } 
} 
+0

Я бы предложил использовать более четкое имя, чем 'NULL', в зависимости от вашего варианта использования. Например, вы можете использовать 'ANONYMOUS' для типа' Person'. – dimo414

+0

Класс 'Nullable' не реализует' .equals() ', что означает, что операции, подобные' map.containsValue() ', будут нарушены. – dimo414

+0

Ярмарка, но это демонстрационный класс. – Virmundi

5

Вместо того чтобы использовать null, который не имеет смысловое значение и, как правило, считается antipattern, представитель «отсутствующий» понятие, как конкретный тип, который отражает ваши намерения и силы звонящим объяснить это правильно.

Общим решением является использование Optional (для pre-Java 8 используйте Guava Optional), чтобы представить отсутствие значения.

Таким образом, ваша карта будет иметь тип ConcurrentHashMap<Key, Optional<Value>>.


Другим вариантом является представление, что вы собираетесь в виду, null более непосредственно в типе вы храните на карте, например, если null должно означать «это не используется существовать, но уже не» вы можете создать структуру классов, так как:

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.