OCP Question 45, Explanation

Given the code fragment:

public class MapPetShow {
    public static void main (String [ ] args) {

        Map<Integer, String> sourceMap = new HashMap<>( );
        sourceMap.put(37, "Ms.Piggy ");
        sourceMap.put(8, "Gonzo ");
        sourceMap.put(4, "Rowlf ");
        sourceMap.put(12, "Fozzie ");
        sourceMap.put(82, "Kermit ");

        Map<Integer, String> finalMap = new TreeMap<Integer, String> (
            new Comparator<Integer> ( ) {
                @Override
                public int compare(Integer obj1, Integer obj2) {
                    return obj2.compareTo(obj1);
        }});

        finalMap.putAll(sourceMap);
        for (Map.Entry<Integer, String> entry : finalMap.entrySet()) {
            System.out.print(entry.getValue());
        }
    }
}

What is the result?

A. A compilation error occurs
B. Rowlf Gonzo Fozzie Ms.Piggy Kermit
C. Kermit Ms.Piggy Fozzie Gonzo Rowlf
D. Rowlf Ms.Piggy Kermit Fozzie Gonzo

 

The correct answer is C.

 

We ask JVM to create the finalMap object by invoking TreeMap‘s ctor with a custom-built Compator as its arg. Why would we do that? Obviously, to override the logic of the natural order of the elements that are being compared. And why should we care abour comparison in the first place? It’s because TreeMap was specifically created as a navigable implementation of the SortedMap interface in order to store its elements in a certain addressable order. So whenever you see a TreeMap on the exam, always start by checking if elements to be sorted implement Comparable (we’ve already met something similar in Problem 11 where those poor doggies didn’t know know how to sort themselves out).

The javadoc for TreeMap says that “The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used”. In our case the keys are of type Integer, so it stands to reason that the custom-built Comparator is most likely intended to flip Integer‘s natural order meaning that the String values will be listed by their keys descending. The biggest key is 82, therefore Kermit the Frog gets the first place… Oh boy, I remember working hand in hand with Kermit the Protocol under CP/M, can you belive that?

Alright, fast forward back to the present. After finalMap has been created, we populate it by invoking the putAll() method, which copies all entries from the source map and sorts them on the fly.

Finally, the for-each construct iterates over the Set returned by entrySet() on finalMap. This Set contains key-value pairs of type Map.Entry, which is a static nested interface in Map. Values are extracted by invoking the getValue() method on each entry… This looks a bit messy so we could probably tidy it up through the wizardry of functional programming. Please try it. Now.

Click here for a suggested solution.
finalMap.entrySet()
        .stream()
        .map(Map.Entry::getValue)
        .forEach(System.out::print);  // Kermit Ms.Piggy Fozzie Gonzo Rowlf

Leave Comment

Your email address will not be published. Required fields are marked *