{"id":"interfaces-map","slug":"map-interface","title":"Java's Map interface","text":"Maps work the same way. HashMap is a class, and it implements an interface called **Map**, also in `java.util`. Map promises what modules 31 to 33 used: `put`, `get`, `getOrDefault`, `containsKey`, `remove`, `size`, `keySet` and `values`. A bakery keeps the day's orders, from each kind of bread to a number of loaves:\n\n```java\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class Main {\n    public static void main(String[] args) {\n        Map<String, Integer> orders = new HashMap<>();\n        orders.put(\"rye\", 4);\n        orders.put(\"sourdough\", 10);\n        orders.put(\"rye\", orders.get(\"rye\") + 2);\n        orders.put(\"baguette\", 7);\n        System.out.println(orders.get(\"rye\"));\n        System.out.println(orders.getOrDefault(\"spelt\", 0));\n        System.out.println(totalLoaves(orders));\n        printOrders(orders);\n    }\n\n    public static int totalLoaves(Map<String, Integer> orders) {\n        int total = 0;\n        for (int loaves : orders.values()) {\n            total += loaves;\n        }\n        return total;\n    }\n\n    public static void printOrders(Map<String, Integer> orders) {\n        List<String> breads = new ArrayList<>(orders.keySet());\n        Collections.sort(breads);\n        for (String bread : breads) {\n            System.out.println(bread + \": \" + orders.get(bread));\n        }\n    }\n}\n```\n\n```output\n6\n0\n23\nbaguette: 7\nrye: 6\nsourdough: 10\n```\n\n- `Map<String, Integer> orders = new HashMap<>();`: the variable's type is the interface, and the object is a HashMap. Map needs its own import, `import java.util.Map;`.\n- Every call you know from HashMap works, since every one of them is in Map.\n- `totalLoaves` and `printOrders` take a Map, so they'd work with any class that implements Map. Java has others, such as `TreeMap`, which keeps its keys in sorted order. This course keeps to HashMap.\n- The object is still a HashMap, so module 31's rule about order still holds: it goes through its keys in an order set by their hash codes. That's why `printOrders` sorts a list of the keys first. The list is a `List<String>` now, like step 6's lists.\n\n### What keySet and values give\n\n`keySet()` and `values()` return interface types too:\n\n- `keySet()` returns a `Set<String>`, a set of the keys. Sets are the next step.\n- `values()` returns a `Collection<Integer>`. Collection is the interface of step 9.\n\nSo far you've used them only in a for-each loop or in `new ArrayList<>(...)`, and both of those accept any Set or Collection.\n\nModule 33's maps of lists can use the interfaces too: `Map<String, List<String>> byClub = new HashMap<>();` holds a List for each key, and each new value can still be made with `new ArrayList<>()`, since an ArrayList is a List.\n","task":"The baker starts with the bread that has the most loaves ordered. Write the method `biggestOrder(Map<String, Integer> orders)`, which returns the kind of bread with the most loaves. The map always has at least one order, and no two kinds have the same number of loaves. The check runs:\n\n```java\nMap<String, Integer> orders = new HashMap<>();\norders.put(\"rye\", 6);\norders.put(\"sourdough\", 10);\norders.put(\"baguette\", 7);\nSystem.out.println(biggestOrder(orders));\n```\n\nand expects:\n\n```\nsourdough\n```\n","kind":"code","seed":"import java.util.HashMap;\nimport java.util.Map;\n\npublic class Main {\n    public static void main(String[] args) {\n        Map<String, Integer> orders = new HashMap<>();\n        orders.put(\"rye\", 6);\n        orders.put(\"sourdough\", 10);\n        orders.put(\"baguette\", 7);\n        System.out.println(biggestOrder(orders));\n    }\n\n    // Write the method biggestOrder here.\n}\n","solution":"import java.util.HashMap;\nimport java.util.Map;\n\npublic class Main {\n    public static void main(String[] args) {\n        Map<String, Integer> orders = new HashMap<>();\n        orders.put(\"rye\", 6);\n        orders.put(\"sourdough\", 10);\n        orders.put(\"baguette\", 7);\n        System.out.println(biggestOrder(orders));\n    }\n\n    public static String biggestOrder(Map<String, Integer> orders) {\n        String biggest = null;\n        for (String bread : orders.keySet()) {\n            if (biggest == null || orders.get(bread) > orders.get(biggest)) {\n                biggest = bread;\n            }\n        }\n        return biggest;\n    }\n}\n","hints":["The header is `public static String biggestOrder(Map<String, Integer> orders)`. Go through `orders.keySet()`, and keep the bread with the most loaves so far.","Start with `String biggest = null;`. A bread becomes the new biggest when `biggest == null`, or when `orders.get(bread) > orders.get(biggest)`."],"tests":[{"name":"Test 1","stdin":"","call":"Map<String, Integer> orders = new HashMap<>();\norders.put(\"rye\", 6);\norders.put(\"sourdough\", 10);\norders.put(\"baguette\", 7);\nSystem.out.println(biggestOrder(orders));\n","expect":"sourdough","hidden":false},{"name":"Test 2","stdin":"","call":"Map<String, Integer> one = new HashMap<>();\none.put(\"spelt\", 1);\nSystem.out.println(biggestOrder(one));\nHashMap<String, Integer> many = new HashMap<>();\nString[] breads = {\"rye\", \"bagel\", \"brioche\", \"focaccia\", \"pretzel\", \"ciabatta\"};\nfor (int i = 0; i < breads.length; i++) {\n    many.put(breads[i], (i * 7) % 11);\n}\nSystem.out.println(biggestOrder(many));\n","expect":"spelt\nfocaccia","hidden":true},{"name":"Test 3","stdin":"","call":"Map<String, Integer> orders = new HashMap<>();\norders.put(\"rye\", 30);\norders.put(\"spelt\", 2);\norders.put(\"brioche\", 29);\nSystem.out.println(biggestOrder(orders));\norders.put(\"spelt\", 31);\nSystem.out.println(biggestOrder(orders));\n","expect":"rye\nspelt","hidden":true}],"require":[{"pattern":"\\bpublic\\s+static\\s+String\\s+biggestOrder\\s*\\(\\s*Map<String,\\s*Integer>\\s+\\w+\\s*\\)","message":"Write the method as `public static String biggestOrder(Map<String, Integer> orders)`."}],"forbid":[],"more":[{"task":"What does this program print?\n","kind":"predict","seed":"import java.util.HashMap;\nimport java.util.Map;\n\npublic class Main {\n    public static void main(String[] args) {\n        Map<String, Integer> orders = new HashMap<>();\n        orders.put(\"rye\", 3);\n        orders.put(\"spelt\", 2);\n        orders.put(\"rye\", 5);\n        addLoaves(orders, \"spelt\", 4);\n        addLoaves(orders, \"bagel\", 12);\n        orders.remove(\"rye\");\n        System.out.println(orders.size() + \" \" + orders.get(\"spelt\"));\n        System.out.println(orders.getOrDefault(\"rye\", 0) + \" \" + orders.containsKey(\"bagel\"));\n    }\n\n    public static void addLoaves(Map<String, Integer> orders, String bread, int loaves) {\n        orders.put(bread, orders.getOrDefault(bread, 0) + loaves);\n    }\n}\n","solution":"import java.util.HashMap;\nimport java.util.Map;\n\npublic class Main {\n    public static void main(String[] args) {\n        Map<String, Integer> orders = new HashMap<>();\n        orders.put(\"rye\", 3);\n        orders.put(\"spelt\", 2);\n        orders.put(\"rye\", 5);\n        addLoaves(orders, \"spelt\", 4);\n        addLoaves(orders, \"bagel\", 12);\n        orders.remove(\"rye\");\n        System.out.println(orders.size() + \" \" + orders.get(\"spelt\"));\n        System.out.println(orders.getOrDefault(\"rye\", 0) + \" \" + orders.containsKey(\"bagel\"));\n    }\n\n    public static void addLoaves(Map<String, Integer> orders, String bread, int loaves) {\n        orders.put(bread, orders.getOrDefault(bread, 0) + loaves);\n    }\n}\n","hints":["A second `put` with the key `rye` replaces its value. `addLoaves` gets the same map object, so what it puts is in `orders`.","Spelt goes from 2 to 6, and bagel starts from 0. After `remove`, rye isn't in the map, so `getOrDefault` gives the default, 0."],"tests":[{"name":"Output","stdin":"","expect":"2 6\n0 true","hidden":false}],"require":[],"forbid":[],"lines":["2 6","0 true"]},{"task":"The bakery lets its customers vote for next month's special bread. Write the method `countVotes(List<String> votes)`, which returns a `Map<String, Integer>` from each kind of bread to the number of votes it got. The check runs:\n\n```java\nList<String> votes = new ArrayList<>();\nvotes.add(\"walnut\");\nvotes.add(\"olive\");\nvotes.add(\"walnut\");\nMap<String, Integer> counts = countVotes(votes);\nSystem.out.println(counts.get(\"walnut\") + \" \" + counts.get(\"olive\"));\nSystem.out.println(counts.size());\n```\n\nand expects:\n\n```\n2 1\n2\n```\n","kind":"code","seed":"import java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<String> votes = new ArrayList<>();\n        votes.add(\"walnut\");\n        votes.add(\"olive\");\n        votes.add(\"walnut\");\n        Map<String, Integer> counts = countVotes(votes);\n        System.out.println(counts.get(\"walnut\") + \" \" + counts.get(\"olive\"));\n        System.out.println(counts.size());\n    }\n\n    // Write the method countVotes here.\n}\n","solution":"import java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\n\npublic class Main {\n    public static void main(String[] args) {\n        List<String> votes = new ArrayList<>();\n        votes.add(\"walnut\");\n        votes.add(\"olive\");\n        votes.add(\"walnut\");\n        Map<String, Integer> counts = countVotes(votes);\n        System.out.println(counts.get(\"walnut\") + \" \" + counts.get(\"olive\"));\n        System.out.println(counts.size());\n    }\n\n    public static Map<String, Integer> countVotes(List<String> votes) {\n        Map<String, Integer> counts = new HashMap<>();\n        for (String vote : votes) {\n            counts.put(vote, counts.getOrDefault(vote, 0) + 1);\n        }\n        return counts;\n    }\n}\n","hints":["The header is `public static Map<String, Integer> countVotes(List<String> votes)`. Inside, make `Map<String, Integer> counts = new HashMap<>();` and return it at the end.","For each vote, count as module 31 did: `counts.put(vote, counts.getOrDefault(vote, 0) + 1);`."],"tests":[{"name":"Test 1","stdin":"","call":"List<String> votes = new ArrayList<>();\nvotes.add(\"walnut\");\nvotes.add(\"olive\");\nvotes.add(\"walnut\");\nMap<String, Integer> counts = countVotes(votes);\nSystem.out.println(counts.get(\"walnut\") + \" \" + counts.get(\"olive\"));\nSystem.out.println(counts.size());\n","expect":"2 1\n2","hidden":false},{"name":"Test 2","stdin":"","call":"List<String> none = new ArrayList<>();\nSystem.out.println(countVotes(none).size());\nArrayList<String> votes = new ArrayList<>();\nfor (int i = 0; i < 9; i++) {\n    votes.add(\"fig\");\n    if (i % 3 == 0) {\n        votes.add(\"rye\");\n    }\n}\nMap<String, Integer> counts = countVotes(votes);\nSystem.out.println(counts.get(\"fig\") + \" \" + counts.get(\"rye\") + \" \" + counts.get(\"olive\"));\n","expect":"0\n9 3 null","hidden":true},{"name":"Test 3","stdin":"","call":"List<String> votes = new ArrayList<>();\nvotes.add(\"Olive\");\nvotes.add(\"olive\");\nSystem.out.println(countVotes(votes).size() + \" \" + votes.size());\n","expect":"2 2","hidden":true}],"require":[{"pattern":"\\bpublic\\s+static\\s+Map<String,\\s*Integer>\\s+countVotes\\s*\\(\\s*List<String>\\s+\\w+\\s*\\)","message":"Write the method as `public static Map<String, Integer> countVotes(List<String> votes)`."}],"forbid":[]}]}