Почему ConcurrentHashMap предотвращает пустые ключи и значения?



документация javadoc в размере ConcurrentHashMap говорит:




как Hashtable но в отличие от HashMap этот класс не разрешить null для использования в качестве ключа или значения.




мой вопрос: почему?



2-й вопрос: почему Hashtable не позволяет null?



я использовал много хэш-карт для хранения данных. Но при переходе на ConcurrentHashMap я несколько раз попадал в неприятности из-за Возникновению исключительных ситуаций типа NullPointerException.

456   6  

6 ответов:

от автора (Дуг Lea):

основная причина, по которой null не допускаются в ConcurrentMaps (ConcurrentHashMaps, ConcurrentSkipListMaps) заключается в том, что лицо, которое может быть просто едва терпимо в непараллельных картах не может быть размещенный. Главное, что если map.get(key) возвращает null, вы не удается определить, явно ли ключ сопоставляется с null против ключа нет сопоставляются. В неконкурентной карте вы можете проверить это через map.contains(key), но в параллельном случае карта могла измениться между вызовами.

Я считаю, что это, по крайней мере частично, чтобы позволить вам сочетать containsKey и get в один вызов. Если карта может содержать нули, нет никакого способа сказать, если get возвращает null, потому что не было ключа для этого значения, или просто потому, что значение было null.

почему это проблема? Потому что нет безопасного способа сделать это самостоятельно. Возьмите следующий код:

if (m.containsKey(k)) {
   return m.get(k);
} else {
   throw new KeyNotPresentException();
}

С m является параллельной картой, ключ k может быть удален между containsKey и get вызовы, в результате чего этот фрагмент возвращает null, который никогда не был в таблице, а не желаемый KeyNotPresentException.

обычно вы решаете это путем синхронизации, но с параллельной картой, которая, конечно же, не будет работать. Отсюда и подпись get пришлось изменить, и единственным способом сделать это обратно совместимым способом было предотвратить вставку пользователем нулевых значений в первую очередь и продолжать использовать это в качестве заполнителя для "ключ не найден".

Джош блох, предназначенные HashMap; Дуг Lea предназначены ConcurrentHashMap. Надеюсь, это не клевета. На самом деле я думаю, что проблема в том, что null часто требуют обертывания, так что реальный null может означать неинициализированный. Если клиентский код требует нулей, то он может оплатить (по общему признанию, небольшую) стоимость обертывания нулей.

вы не можете синхронизировать на null.

Edit: это не совсем то, почему в этом случае. Я изначально думал, что было что-то необычное происходит с блокировкой вещей против параллельных обновлений или иным образом с помощью монитора объектов, чтобы обнаружить, если что-то было изменено, но после изучения исходный код похоже, я ошибся-они блокируют использование "сегмента" на основе битовой маски хэша.

в таком случае, я подозреваю, что они сделали это, чтобы скопировать Hashtable, и я подозреваемый Hashtable сделал это, потому что в мире реляционных баз данных, null != нуль, поэтому использование null в качестве ключа не имеет смысла.

ConcurrentHashMap является потокобезопасным. Я считаю, что не позволяя null ключи и значения были частью убедившись, что это потокобезопасно.

Я думаю, что следующий фрагмент документации API дает хороший намек: "Этот класс полностью совместим с Hashtable в программах, которые полагаются на его потокобезопасность, но не на его деталях синхронизации."

Они, наверное, просто хотел сделать ConcurrentHashMap полностью совместимы/взаимозаменяемы Hashtable. И как Hashtable не допускает null-ключей и значений..

Comments

    Ничего не найдено.