Почему ConcurrentHashMap предотвращает пустые ключи и значения?
документация javadoc в размере ConcurrentHashMap говорит:
как
Hashtableно в отличие отHashMapэтот класс не разрешитьnullдля использования в качестве ключа или значения.
мой вопрос: почему?
2-й вопрос: почему Hashtable не позволяет null?
я использовал много хэш-карт для хранения данных. Но при переходе на ConcurrentHashMap я несколько раз попадал в неприятности из-за Возникновению исключительных ситуаций типа NullPointerException.
6 ответов:
основная причина, по которой 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