Почему есть разница в выходе, просто меняя значения ключей в ConcurrentHashMap - PullRequest
0 голосов
/ 26 октября 2018

enter image description here

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

Ответы [ 2 ]

0 голосов
/ 26 октября 2018

Вероятно, есть причина, по которой вы использовали ConsurrentHashMap вместо обычной Map реализации, такой как HashMap.Если вы попытаетесь использовать одну из этих реализаций и запустить свой код, вы заметите ConcurrentModificationException, которое может быть выброшено всякий раз, когда вы обновляете HashMap во время итерации по нему.Если вы измените эту реализацию на ConcurrentHashMap, это изменит следующее:

Хеш-таблица, поддерживающая полный параллелизм получения и высокий ожидаемый параллелизм для обновлений.[...] Операции извлечения (включая get) обычно не блокируются, поэтому могут перекрываться с операциями обновления (включая put и remove).Извлечения отражают результаты самых последних завершенных операций обновления, сохраняющих их начало.

Таким образом, одновременные обновления разрешены, пока вы выполняете итерацию по Map.Теперь вопрос, можете ли вы на самом деле увидеть значение или нет, может быть связан с порядком итераций реализации Map (который может меняться в зависимости от версии Java, поскольку в обычно нет порядка итерации в Map).Если элемент вставлен перед текущей итерацией, он не будет повторен.Если элемент вставлен после, он печатается на консоли.В конце концов, вы не должны на это полагаться.

Однако, если вы снова зациклите Map

Iterator<String> it = map.keySet().iterator();
while (it.hasNext()) {
    System.out.println(map.get(it.next()));
}

, вы правильно увидите значение в выводе:

iPhone
HTC one
S5
Xperia Z <<< here it is
iPhone
HTC one
S5

То, что предыдущее предположение верно, теперь можно доказать, поскольку ключ «Sony» был повторен первым, поэтому он не будет отображаться в предыдущей итерации.Если вы сравните это с первой попыткой, клавиша "d" была повторена последней, поэтому она отображается на консоли.Если быть точным, если у вас есть значение, которое повторяется, а не первое значение, оно будет отображаться (поскольку вы добавляете его уже на второй итерации).

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

0 голосов
/ 26 октября 2018

ConcurrentHashMap.iterator () не гарантирует, что вы добавите или не увидите добавленную запись во время итерации по ней.Существует внутренний порядок, в котором он проходит над записями, и если вы добавите до точки, до которой он находится, вы не увидите запись.

Если вы снова итерируете значения, вы увидите, что во второмбыл до первой записи.

...