Java Arena
Step 2 of 5

One value per key

A key is linked to at most one value. Putting a key that's already in the map doesn't add a second pair: the new value takes the place of the old one.

The front desk of a small hotel keeps the name of the guest in each room, with the room numbers as keys. Keys can be numbers too, and like values, they're Integer, not int. put(204, "Okafor") turns the 204 into an Integer by itself.

HashMap<Integer, String> guests = new HashMap<>();
guests.put(204, "Okafor");
guests.put(310, "Lindqvist");
System.out.println(guests.get(204) + ", " + guests.size() + " rooms taken");

guests.put(204, "Tanaka");
System.out.println(guests.get(204) + ", " + guests.size() + " rooms taken");
Output
Okafor, 2 rooms taken
Tanaka, 2 rooms taken
  • size() is the number of keys in the map, which is also the number of pairs.
  • The second put(204, ...) replaced Okafor with Tanaka. The map still has two pairs, and Okafor isn't in it anymore.
  • Values have no such rule. Two rooms can have guests with the same name, since the rooms are different keys.

(When a key needs several values, such as all the guests of a room, the value can be a list. Module 33 does that.)

Checking and removing

Method What it does
containsKey(key) true if the key is in the map, otherwise false
remove(key) removes the key and its value; a key that isn't there changes nothing
size() the number of keys
isEmpty() true when the map has no keys at all
HashMap<Integer, String> guests = new HashMap<>();
guests.put(204, "Tanaka");
guests.put(310, "Lindqvist");

System.out.println(guests.containsKey(310));
guests.remove(310);
System.out.println(guests.containsKey(310) + " " + guests.get(310));
guests.remove(512);
System.out.println(guests.size() + " " + guests.isEmpty());
guests.remove(204);
System.out.println(guests.size() + " " + guests.isEmpty());
Output
true
false null
1 false
0 true

Since put replaces, a program that must not lose a value checks first. Here a new guest gets a room only if nobody is in it:

if (guests.containsKey(room)) {
    System.out.println("Room " + room + " is taken");
} else {
    guests.put(room, guest);
}

Keys must match exactly

get, containsKey and remove find a key only if it's equal to a key in the map. The map works out the key's hash code, looks only at the keys with that same hash code, and uses equals to tell whether one of them is equal. (Module 32 shows why both of those matter.) For Strings, equal means that every character is the same: "lis" and "LIS " are different keys from "LIS". Keys that people type often come with small letters or extra spaces, so tidy them into the map's form first:

import java.util.HashMap;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        HashMap<String, String> airports = new HashMap<>();
        airports.put("HEL", "Helsinki");
        airports.put("LIS", "Lisbon");

        String typed = scanner.nextLine();
        System.out.println("As typed: " + airports.get(typed));
        String code = typed.trim().toUpperCase();
        System.out.println("Tidied: " + airports.get(code));
    }
}
Input
  lis
Output
As typed: null
Tidied: Lisbon
  • trim() removes the spaces at the start and the end, and toUpperCase() turns the letters into capitals (module 16). The map's codes are in capitals, so the tidied code matches.
  • Choose one form for the keys, such as capitals for codes or small letters for words and titles, and tidy every key into it: when you put it, and when you look it up.

Your task

Challenge 1 of 3

What does this program print? One room is put twice, and one guest's name is in the map twice.

Challenge 2

A pantry keeps its jars in a HashMap<String, Integer>: each food, and how many jars of it there are. A food is in the map only while there's at least one jar of it. Write the method useOne(HashMap<String, Integer> jars, String food). If the pantry has the food, the method takes one jar away and returns true, and when that was the last jar, it removes the food from the map. If the pantry has no such food, the method changes nothing and returns false. The check runs:

HashMap<String, Integer> jars = new HashMap<>();
jars.put("marmalade", 2);
jars.put("olives", 1);
System.out.println(useOne(jars, "marmalade") + " " + jars.get("marmalade"));
System.out.println(useOne(jars, "olives") + " " + jars.containsKey("olives"));
System.out.println(useOne(jars, "olives") + " " + jars.size());

and expects:

true 1
true false
false 1

Challenge 3

A radio station takes song requests by text message, and people type the titles any way they like. The map catalog has every song the station can play, with the title in small letters as the key and the artist as the value. Read requests, one per line, until an empty line. Tidy each title with trim() and toLowerCase(), and then print either Playing , the tidied title, by and the artist, or Not in the catalog: and the tidied title. For the input shown, the program prints:

Playing night bus by Mira Vale
Playing paper lanterns by The Quiet Hours
Not in the catalog: blue tuesday