2016-01-30 2 views
1

Почему этот метод не вызывает одновременную модификацию? если если (next.equals («3») это не так. Однако я изменить его на равных («1») это делает. Что здесь происходит?почему итератор не выбрасывает исключение одновременной модификации?

private void checkConcurrentModification(){ 

     Map<String, Integer> map = new HashMap<>(); 

     map.put("1", 1); 
     map.put("2", 2); 
     map.put("3", 3); 


     Iterator<Entry<String, Integer>> iterator = map.entrySet().iterator(); 

     while(iterator.hasNext()){ 
      String next = iterator.next().getKey(); 
      map.put(next, 1); 
      if(next.equals("3")){ //does not throw exception 
//if(next.equals("1")){ //throws exception 
       map.put("4", 4); 
      } 
     } 

     for(Entry<String, Integer> entry : map.entrySet()){ 
      System.out.println("entry key and value" +entry.getKey() + " : " +entry.getValue()); 
     } 

    } 


prints: 
entry key and value1 : 1 
entry key and value2 : 1 
entry key and value3 : 1 
entry key and value4 : 4 
+0

Я получаю 'ConcurrentModificationException' для примера, как написано (с' 3'). – RealSkeptic

+0

nope. вызывающий из основной. – Bharath

ответ

2

Это зависит от реализации HashMap.

Если запустить это под Java 7, то с if (next.equals("3")) он будет бросать ConcurrentModificationException, и с 1, он не будет.

Если запустить это под Java 8, а затем с 3 он будет не выбрасывайте исключение, и с 1, это будет.

Причина этого в том, что при повторной итерации карты под Java 7 первым ключом будет 3, а последний - 1. Таким образом, вы изменяете значение, пока у вас все еще есть другие значения для итерации.

В Java 8 первый ключ итерации - 1, а последний - 3.

Если изменить карту, когда вы столкнулись последний ключ, он не будет проверять, что изменение, потому что он только проверяет его в следующий раз, когда вы пытаетесь позвонить next(), но после последнего значения, hasNext() возвращает ложь, так next() не вызывается и исключение исключается.

+0

_Если вы запускаете это под Java 8, то с 3 он не будет генерировать исключение, а с 1 будет. Я использую Java 8. Но этого не происходит. – Satya

+0

Спасибо. При дальнейшей проверке класса HashIterator вызов hasNext на итераторе (hashIterator) проверяет только следующее: = null. Однако метод next() проверяет if (modCount! = ExpectedModCount) throw new ConcurrentModificationException(); , и поэтому исключение выбрано. – Bharath

2

ConcurrentModificationException не выбрасывается, пока вы не попытаетесь получить доступ к iterator.next().getKey(); после изменения карты в пределах цикла. В примере "3" является последним ключом на исходной карте, и цикл выходит до того, как будет выбрано исключение. Для каждого ключа исходной карты, кроме последней, будет выбрано исключение.

1

ConcurrentModificationException бросается, когда итератор достигает следующего ключа карты, если вы добавили новый ключ к карте на предыдущем шаге. Таким образом, вы получаете только исключение, если ключ, который вы тестируете, не является последним на карте. В вашем случае 3 - это, безусловно, последний.

Примечание: Поскольку HashMap не имеет порядок, на одной машине 3 может быть последним, на других 1 или 2 может быть.

Смежные вопросы