1

Consider the function below:

private static void printTrie(Node root){
        Iterator it = root.children.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry pair = (Map.Entry)it.next();
            System.out.println((Character)pair.getKey());
            root = (Node)pair.getValue();
            printTrie(root);
            it.remove(); // avoids a ConcurrentModificationException
        }
    }

Here's the definition of Node:

static class Node {
        private HashMap<Character, Node> children;
        private boolean isCompleteContact;

        public Node(){
            children = new HashMap<Character, Node>();
            isCompleteContact = false;
        }
    }

My question is this: in the function I create an Iterator called it based on root. However, halfway through iterating over all the elements exposed by it, I reassign root to another node. Does this change the behaviour of the it? I.e., does it still refer to the original root or the new value we assign to root halfway through the while loop?

Chetan Kinger
  • 15,069
  • 6
  • 45
  • 82
Adam
  • 8,752
  • 12
  • 54
  • 96

2 Answers2

2

It refers to the original object root was referring to. This is because the iterator is derived from the value of the variable root, rather than it, itself, as a reference to that value.

Horia Coman
  • 8,681
  • 2
  • 23
  • 25
1

Since Java is always pass-by-value, the reassignment of the root reference will not reassign the root object/instance but just the root reference.

The statement root = (Node)pair.getValue(); only reassings the local reference root to a new object. You will continue to iterate over the original root object since the iterator was created on the original root object which can't be reassigned due to pass-by-value semantics.

Also note that if you add a new value to the children HashMap while iterating over it, it will result in a ConcurrentModficationException. The only thing you can do safetly using the same iterator is remove the current element being iterated by calling remove on the Iterator

Chetan Kinger
  • 15,069
  • 6
  • 45
  • 82
  • But if I changed the original root object somehow, the `it` would reflect that change? – Adam Jan 23 '17 at 18:06
  • Depends on what you mean by changing the original root object. If you mean changing the *state* of the root object, then yes, it is possible for this change to be reflected in the `iterator` provided that the `iterator` relies on this state and allows such an update. See [this](http://stackoverflow.com/questions/223918/iterating-through-a-collection-avoiding-concurrentmodificationexception-when-re) as an example. I don't see how you would reassign the original root object/instance itself (like I said, Java uses pass-by-value semantics always) – Chetan Kinger Jan 23 '17 at 18:20
  • So if I added something to the HashMap halfway through iterating over it, the iterator would be aware of the change in the sense that it would provide access to the new object? Or would I have to create a new iterator to get access to the new object? – Adam Jan 23 '17 at 20:03