Start learning free

LESSON 127 OF 671 · DICTIONARIES

Reading a Missing Key in Java with getOrDefault

Lesson Read the full explanation

TL ; DR:

map.getOrDefault(key, 0) gives the key's value, or 0 when the key is missing.


HashMap<String, Integer> points = new HashMap<>();
points.put("Ana", 7);

System.out.println(points.getOrDefault("Ana", 0));   // 7
System.out.println(points.getOrDefault("Ben", 0));   // 0


Full lesson:

A missing key often means "none yet". A player with no points yet has 0 points.

points.get("Ben") gives null. Storing that null in an int crashes the program with a NullPointerException.

getOrDefault takes a key and a default. It gives the key's value when the key is there. It gives the default when it isn't.

Reading this way doesn't add the key. points still has one key afterwards.

It does what this if with containsKey does, in one line:

int score = 0;
if (points.containsKey("Ben")) {
    score = points.get("Ben");
}

Your task

stock counts the fruit in a shop. The code reads and prints the pears.

There are no plums yet. Read "plums" with getOrDefault and 0 as the default. Store it in an int named plums.

Then print the plums line, the same way as the pears line.

Expected output:

We have 2 pears
We have 0 plums
STEP 1 OF 2
    Ctrl + Enter to check

    JAVA · DICTIONARIES

    Dictionary Default Value in Java, explained

    A missing key often means "none yet"

    In a shop's stock count, a fruit that is not in the map simply means the shop has none. The natural answer for "how many plums?" is 0, not an error. But stock.get("plums") returns null for a missing key, and a null cannot be stored in an int. Java tries to unbox it and throws a NullPointerException:

    HashMap<String, Integer> stock = new HashMap<>();
    stock.put("apples", 5);
    stock.put("pears", 2);
    
    System.out.println(stock.get("plums"));   // null
    int plums = stock.get("plums");           // NullPointerException
    

    getOrDefault

    map.getOrDefault(key, fallback) takes a key and a default. It returns the key's value when the key is in the map, and the default when it is not.

    System.out.println(stock.getOrDefault("apples", 0));   // 5
    System.out.println(stock.getOrDefault("plums", 0));    // 0
    

    Reading this way does not add the key. After the calls above, stock.size() is still 2.

    The same thing with containsKey

    Before getOrDefault, the usual way was an if with containsKey:

    int plums = 0;
    if (stock.containsKey("plums")) {
        plums = stock.get("plums");
    }
    

    getOrDefault is that whole block in one line: int plums = stock.getOrDefault("plums", 0);.

    The null check, spelled out

    A third way is to keep the result in an Integer, which can hold null, and fix it by hand: Integer n = stock.get("plums"); if (n == null) { n = 0; }. That leaves n as 0 here. It works, but it is more code than getOrDefault for the same idea, and easy to get wrong if you declare n as an int by mistake, since an int can never be compared with null.

    Choosing the default

    The default can be any value of the map's value type. For counts it is 0. For a HashMap<String, String> it could be a text such as "unknown". Pick the value that means "nothing yet" for your data.

    Details

    The default is returned only when the key is not in the map. If the key is present with a null value, getOrDefault returns that null, not the fallback. Maps of counts normally never hold null, so this rarely matters. On a map with string values, fl.getOrDefault("x", "unknown") on an empty fl returns unknown.

    The exercise

    The map stock holds 5 apples and 2 pears. The pears are read and printed with get, which is safe because the key exists. There are no plums, so:

    1. Read the plums with stock.getOrDefault("plums", 0) and store the result in an int named plums. It is 0.
    2. Print the line the same way as the pears line, with plums in place of pears.
    HashMap<String, Integer> stock = new HashMap<>();
    stock.put("apples", 5);
    stock.put("pears", 2);
    
    int pears = stock.get("pears");
    System.out.println("We have " + pears + " pears");
    
    int plums = stock.getOrDefault("plums", 0);
    System.out.println("We have " + plums + " plums");
    

    Output:

    We have 2 pears
    We have 0 plums
    

    Common mistakes

    • Using get for a key that may be missing. Printing stock.get("plums") shows null, and putting it in an int crashes.
    • Expecting the key to be created. After getOrDefault("plums", 0), containsKey("plums") is still false and the size has not changed. To store the key, call put. A counter that reads with a default and writes with put is a very common pattern: stock.put("apples", stock.getOrDefault("apples", 0) + 1) changes apples from 5 to 6.
    • A default of the wrong type. The fallback must fit the map's value type: an int for Integer values, a string for string values.

    Key takeaways

    • get returns null for a missing key, and unboxing that null into an int throws NullPointerException.
    • getOrDefault(key, fallback) returns the value, or the fallback when the key is missing.
    • It does not add the key to the map.
    • It replaces the containsKey check plus get with one call.
    Keep going with Java500+ step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free