CSE190L Notes for Monday, 4/23/07

I spent more time discussing issues related to collections and iterators. We had seen on Friday that when you construct a collection like a list:

        List<String> lst = new ArrayList<String>();
        lst.add("how");
        lst.add("are");
        lst.add("you");
you can ask for an iterator to process the list:

        Iterator<String> iter = lst.iterator();
        while (iter.hasNext()) {
            String next = iter.next();
            System.out.println(next);
        }
but you have to be careful not to modify the list while iterating unless you do it through the iterator itself. Otherwise you get a ConcurrentModificationException.

I pointed out that the same is true of for-each loops. For example, if we say:

        for (String s : lst) {
            System.out.println(s);
            if (s.startsWith("h"))
                lst.remove(s);
        }
we get a ConcurrentModificationException. That's because the for-each loop is implemented using an iterator. Unfortunately, there is no easy fix to this with a for-each loop. There is no way to request access to the iterator it is using. The bottom line is that for-each loops should be used only when you aren't modifying the list. If you want to make a change like this, write it with an iterator:

        Iterator<String> iter = lst.iterator();
        while (iter.hasNext()) {
            String s = iter.next();
            System.out.println(s);
            if (s.startsWith("h"))
                iter.remove();
        }
We saw on Friday that some methods of a collection can't be called while you iterate over it (like remove), but others can be called (like size or get). The distinction is between what are called accessors and mutators. You should become familiar with that terminology. Accessors are methods that examine the state of an object without changing it. Mutators potentially change the state of the object. Accessors and mutators are also sometimes referred to as "getters" and "setters".

The key issue for an iterator is that you can not call a mutator on the collection while iterating over it. Any mutation would have to be done by the iterator itself. But you can call as many accessors as you want.

Then we spent some time discussing how to use iterators for a Map. Map objects do not have their own iterators and you can use a map in a for-each loop. Instead, the Map gives you three different views of the Map information:

I asked people why the keys are given as a set but the values are not. The answer is that the keys are required to be unique in a map, which means the collection of keys will form a set. The same is true of the key/value pairs, since there will be no repeated keys. But any given value might appear multiple times, so the values are returned as a generic Collection.

I used DrJava to explore some of the issues related to maps. I began by defining and initializing a map with three entries:

        > import java.util.*;
        > Map<String, Integer> m = new HashMap<String, Integer>();
        > m.put("four", 8)
        null
        > m.put("score", 12)
        null
        > m.put("and", 17)
        null
        > m.size()
        3
        > m
        {and=17, score=12, four=8}
We were able to see the fact that no duplicate keys are allowed by calling put again with one of the keys we've already included:

        > m.put("four", 7)
        8
        > m.size()
        3
        > m
        {and=17, score=12, four=7}
Notice that the size did not change. Instead, the new key/value pair replaces the old. Now four is linked to 7 instead of 8. As you can see, the call on put returns the old mapping for the key. Initially we were getting null when we made this call because those keys weren't yet in the map. Here we're getting the value 8 because that's the old pairing that we're replacing.

The entry set is defined in terms of an inner interface. Map itself is an interface that has inside it an interface called Entry, so we refer to it as Map.Entry. I pointed out that accessing the entry set leads to some pretty hairy syntax:

        > Set<Map.Entry<String, Integer>> s = m.entrySet()
        > s
        [and=17, score=12, four=7]
Once we have this set, we can ask for an iterator over the set or we can do a for-each loop:

        > Iterator<Map.Entry<String, Integer>> i = s.iterator()
        > while (i.hasNext()) {
            System.out.println(i.next());
        }
        and=17
        score=12
        four=7

        > for (Map.Entry<String, Integer> entry : s) {
             System.out.println(entry);
        }
        and=17
        score=12
        four=7
Although we can do it this way, the syntax is a bit much. Most people instead iterate over the key set. So in a for-each loop, we can say:

        > for (String s : m.keySet()) {
             System.out.println(s);
             System.out.println(m.get(s));
        }
        and
        17
        score
        12
        four
        7
We can also ask for an iterator for the key set and use it to change the underlying map:

        > Iterator<String> i2 = m.keySet().iterator()
        > while (i2.hasNext()) {
             String next = i2.next();
             System.out.println(next);
             if (next.equals("and"))
                 i2.remove();
        }
        and
        score
        four
We saw that this changed the map itself:

        > m
        {score=12, four=7}
This is how it's done with maps. They don't have their own iterators, so you instead iterate over one of these three collections. We saw in the documentation for keySet that:

The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.
I then spent some time talking about the fact that we want to start on the group project immediately after the midterm, so people should start thinking about forming groups. We will have groups of 3 or 4 students.

In forming your groups, it's a good idea to think about personality issues. I spent some time talking about the Meyers Briggs personality test. There are many excellent online sources like wikipedia and keirsey.com, so I won't try to repeat it here in the notes.


Stuart Reges
Last modified: Wed Apr 25 11:44:23 PDT 2007