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

JavaDoc of ConcurrentHashMap говорит следующее:

Подобно Hashtable но в отличие от HashMap , этот class не позволяет использовать null в качестве ключа или значения.

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

Второй вопрос: почему Hashtable не допускает null?

Я использовал много HashMaps для хранения данных. Но при переходе на ConcurrentHashMap я несколько раз попадал в проблему из-за NullPointerExceptions.

От автора ConcurrentHashMap (Doug Lea) :

Основная причина, по которой nulls не допускаются в ConcurrentMaps (ConcurrentHashMaps, ConcurrentSkipListMaps), заключается в том, что нельзя допускать двусмысленности, которые могут быть едва допустимы в неконкурентных картах. Главное, что если map.get(key) возвращает значение 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 , заставляя этот fragment возвращать нуль, который никогда не был в таблице, а не желаемое KeyNotPresentException .

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

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

Вы не можете синхронизировать с нулевым значением.

Изменить: Это не совсем так в этом случае. Первоначально я думал, что есть что-то фантастическое в том, что происходит с блокировкой вещей от параллельных обновлений или иным образом с помощью монитора объектов, чтобы определить, было ли что-то изменено, но, изучив исходный код, я обнаружил, что ошибался – они блокируют использование «сегмента» на основе битовая маска hashа.

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

ConcurrentHashMap является streamобезопасным. Я считаю, что отказ пустых ключей и значений был частью обеспечения безопасности streamов.

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

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

  • Весна вперед с добавленными параметрами?
  • Java Set сохранить порядок?
  • ojdbc14.jar против ojdbc6.jar
  • Что означает «URI имеет компонент полномочий»?
  • Понимание логики в CaseInsensitiveComparator
  • Разгрузка classов в java?
  • Невозможно создать кэшированный пул streamов с ограничением размера?
  • В чем разница между переменной, объектом и ссылкой?
  • Гик-помощь вводится глубже по иерархии зависимостей
  • Зимует-Викисклад annotations-4.0.1.Final.jar; недопустимый заголовок LOC (плохая подпись)?
  • В JDK 1.8 отображается искажение качания, исправлено в JDK 1.7
  • Давайте будем гением компьютера.