简体   繁体   中英

Valid iterator on a removed list?

I wrote some code that works but I'm not sure. Consider

LinkedList<Iterator<Integer>> iterators;
HashMap<Character, TreeSet<Integer>> map;
for (char c : map.keySet()) {
    iterators.add(map.get(c).iterator());
    map.remove(c);
}

Even though the original TreeSet has been removed, the iterator seems to work fine (ie goes in the original ordering of the TreeSet). I don't quite understand why it's functional--it seems as though there's passing-by-value here instead of passing-by-reference. However, obviously, if I were to write

map.get(c).add(6);

the TreeSet would actually add 6 in the map (not just add 6 to a copy of the TreeSets in the map), indicating get is passing by reference. Can someone help clear up the confusion here?

Removing the TreeSet from the HashMap doesn't destroy the TreeSet ; it just removes the reference in the HashMap to the TreeSet . The HashMap doesn't contain a copy of the TreeSet , just a reference to the TreeSet .

At first:

{map} -----> {aTreeSet}
                  |
                  v
                 {6}

The Iterator 's purpose is to iterate over something. In this case, the logical way for it to iterate over the TreeSet elements is to maintain its own reference to the TreeSet (or an internal data structure within the TreeSet ). The elements are always referred to by at at least one strong reference, so they are never garbage collected.

When the Iterator is created:

{map} -----> {aTreeSet} <----- {Iterator}
                  |
                  v
                 {6}

After removal from the map (and the addition to the LinkedList ):

{map}        {aTreeSet} <----- {Iterator} <----- {iterators}
                  |
                  v
                 {6}

To summarize, the TreeSet elements are never eligible for garbage collection; there is only one TreeSet object, and the elements of it are still available for iteration.

I read your post 5 times and I can't still get where's the confusion?

You're asking why after removing entry from Map you still have working iterator in iterators ? That's how references in Java works...

Line:

iterators.add(map.get(c).iterator());

creates new strong reference to TreeSet which is under c , so this set won't be gced.

When it comes to pass-by-reference vs. pass-by-value - there is nothing like true pass-by-reference known from C/C++. For details look here .

When it comes to line:

map.get(c).add(6);

I have no clue what do you mean by

the TreeSet would actually add 6 in the map (not just add 6 to a copy of the TreeSets in the map)

what do you mean by copy of the TreeSets in map ? Copy of what? It points to the same TreeSet as iterator from iterators points at.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM