1

Today I study deleting the special object from the java.util.HashMap. I test the wrong syntax. But I encountered a fantastic problem. The message on the console is not in the order. The exception message is printed by the wrong order. It seems the the program executes with multithreading. The following is my code.

package com.study.iter;

import java.util.HashMap;
import java.util.Map;

public class TestRmObjFromMap {

    public static void main(String[] args) {

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

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

        remove1(map);
    }

    private static void remove1(Map<String, Integer> map) {

        for(Map.Entry<String, Integer> entry : map.entrySet()) {

            if(entry.getKey().equals("3")) {
                map.remove(entry.getKey());
            }
            else {
                System.out.println("key: " + entry.getKey() + " -- value: " + entry.getValue());
            }

        }

    }

}

After I run this code, it print the following:

Exception in thread "main" java.util.ConcurrentModificationException
key: 1 -- value: 1
key: 2 -- value: 2
    at java.util.HashMap$HashIterator.nextNode(HashMap.java:1437)
    at java.util.HashMap$EntryIterator.next(HashMap.java:1471)
    at java.util.HashMap$EntryIterator.next(HashMap.java:1469)
    at com.study.iter.TestRmObjFromMap.remove1(TestRmObjFromMap.java:29)
    at com.study.iter.TestRmObjFromMap.main(TestRmObjFromMap.java:24)

Why the exception message is divided by other message. Why not like this:

key: 1 -- value: 1
key: 2 -- value: 2
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextNode(HashMap.java:1437)
    at java.util.HashMap$EntryIterator.next(HashMap.java:1471)
    at java.util.HashMap$EntryIterator.next(HashMap.java:1469)
    at com.study.iter.TestRmObjFromMap.remove1(TestRmObjFromMap.java:29)
    at com.study.iter.TestRmObjFromMap.main(TestRmObjFromMap.java:24)

Who can tell me the reason? Thanks!

Now is a simple test:

public static void main(String[] args) {

    for(int i=0;i<500;i++) {
        System.out.println("ttt");
        if(i==10) throw new ConcurrentModificationException();
    }

}

the result:

Exception in thread "main" java.util.ConcurrentModificationException
    ttt
    at com.study.iter.TestIter.main(TestIter.java:14)
    ttt
    ttt
    ttt
    ttt
    ttt
    ttt
    ttt
    ttt
    ttt
    ttt

The reason:

 Exceptions will printed at stderr and System.out.println prints on stdout. Both streams are not sychronized

Thanks!

qinghua
  • 107
  • 1
  • 6
  • @MuratK. wrong duplicate, did you read the question? – kryger Mar 01 '18 at 12:21
  • @BrunoCarletti Read the question carefully. The question is not why OP get the exception – Jens Mar 01 '18 at 12:30
  • 1
    @BrunoCarletti People the question asks about the order of the print statements, not about the exception. – kutschkem Mar 01 '18 at 12:31
  • You are right, sorry my mistake. – Bruno Carletti Mar 01 '18 at 12:37
  • 1
    Possible duplicate of [Iterating through a Collection, avoiding ConcurrentModificationException when removing in loop](https://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re) – Uwe Plonus Mar 01 '18 at 13:37

2 Answers2

7

Exceptions will printed at stderr and System.out.println prints on stdout. Both streams are not sychronized

Jens
  • 67,715
  • 15
  • 98
  • 113
-1

In a HashMap the iteration order is not guaranteed to be the insertion order, i.e. the data can be returned in any order its likes.

To have iteration order the same as insertion order use a LinkedHashMap instead

e.g

Map<String, Integer> map = new LinkedHashMap();
Paul Taylor
  • 13,411
  • 42
  • 184
  • 351