Advanced Key-Based Operations

The following methods for a map take a function (implemented by a lambda expression or a method reference) as a parameter to implement various scenarios that manipulate the value associated with a key.

Click here to view code image

default V merge(K key, V value,
                BiFunction<? super V,? super V,? extends V> remappingFunc)

If the specified key has no entry or is associated with a null value, the method associates the key with the specified non-null value. Otherwise, it associates the key with the result of applying the remapping two-arity function to the specified value and the currently associated value, or removes the entry for the key if the result is null.

Note that if the specified value is null, a NullPointerException is thrown at runtime.

Returns the new value associated with the key, or null if entry for the key is removed.

Click here to view code image

default V compute(K key,
                  BiFunction<? super K,? super V,? extends V> remappingFunc)

The remapping two-arity function is applied to the specified key and its currently associated value. If the result is non-null, it associates the key with the result. Otherwise, it removes any entry for the key.

Returns the computed value associated with the key, or null if the key is removed or is not associated with a value.

Click here to view code image

default V computeIfAbsent(K key,
                          Function<? super K,? extends V> mappingFunc)

If the value associated with the specified key is null or the key has no entry, this method applies the given function on the key, and the result is only associated with the key if the result is non-null.

Returns the current (existing or computed) value associated with the specified key, or null if the computed value is null.

Click here to view code image

default V computeIfPresent(K key,
                           BiFunction<? super K,? super V,? extends V> remappingFunc)

If the specified key is already associated with a non-null value, the method applies the specified remapping two-arity function to the key and its currently associated value. The result is only associated with the key if it is non-null; otherwise, the key is removed.

This method returns the current (existing or computed) value associated with the specified key, or null if the key is absent or removed.

Table 15.6 summarizes typical scenarios when using these advanced key-based methods. Given the value associated with a key and the resultValue returned by the remapping function if it is executed, the action performed and the value returned by each method are shown for each scenario.

Table 15.6 Summary of Scenarios Using Advanced Key-Based Operations

The value associated with key in the mapThe resultValue returned by the remapping functionmerge(key, givenValue, remapping-BiFunction) and (givenValue != null)compute(key, remapping-BiFunction)computeIf-Absent(key, mapping-Function)computeIf-Present(key, remapping-BiFunction)
non-nullnullremove(key), returns null.remove(key), returns null.No change. Returns value.remove(key), returns null.
non-nullnon-nullput(key, resultValue), returns resultValue.put(key, result-Value), returns resultValue.No change. Returns value.put(key, result-Value), returns resultValue.
nullnullput(key, givenValue), returns givenValue.remove(key), returns null.No change. Returns null.No change. Returns null
nullnon-nullput(key, givenValue), returns givenValue.put(key, result-Value), returns resultValue.put(key, result-Value), returns resultValue.No change. Returns null.
No mappingnullput(key, givenValue), returns givenValue.Not entered. Returns null.Not entered. Returns null.Not entered. Returns null.
No mappingnon-nullput(key, givenValue), returns givenValue.put(key, result-Value), returns resultValue.put(key, result-Value), returns resultValue.Not entered. Returns null.

In the code snippets to illustrate each method, an emergency telephone number map, etnMap, is loaded with the same entries. This map is a HashMap<Integer, String> that is used to map emergency telephone numbers (Integers) to countries (Strings) where they are used. (Disclaimer: There is no guarantee that the information provided below is correct.)

Click here to view code image

Map<Integer, String> etnMap = new HashMap<>();
etnMap.put(112, “Norway”);
etnMap.put(999, “UK”);
etnMap.put(190, null);
etnMap.put(911, null);
// {112=Norway, 999=UK, 190=null, 911=null}

In the code below, six method calls are made corresponding to the column for each method in Table 15.6. Each method call shows the value returned by the method as a comment in the call statement.

The merge() method executes as follows:

  • If the key is associated with the null value in the map, as shown at (3) and (4), or has no entry, as shown at (5) and (6), the key is associated with the non-null given value.
  • Otherwise, the remapping two-arity function is computed.
    • If the result is null, the entry for the key is removed, as shown at (1).
    • If the result is non-null, the key is associated with the result, as shown at (2).

Click here to view code image

// Before: {112=Norway, 999=UK, 190=null, 911=null}
etnMap.merge(112, “Mordor”, (oVal, value) -> null);      // (1) null, removed
etnMap.merge(999, “Mordor”, (oVal, value) -> “Uganda”);  // (2) Uganda, updated
etnMap.merge(190, “Mordor”, (oVal, value) -> null);      // (3) Mordor, updated
etnMap.merge(911, “Mordor”, (oVal, value) -> “USA”);     // (4) Mordor, updated
etnMap.merge(100, “Mordor”, (oVal, value) -> null);      // (5) Mordor, inserted
etnMap.merge(110, “Mordor”, (oVal, value) -> “China”);   // (6) Mordor, inserted
// After: {100=Mordor, 999=Uganda, 110=Mordor, 190=Mordor, 911=Mordor}

The compute() method executes as follows:

  • The remapping two-arity function is executed.
    • If this result is non-null, as at (8), (10), and (12), this result is associated with the key whether or not the key has an entry in the map.
    • If this result is null and the key has an entry in the map, the entry is removed, as at (7) and (9).
    • If this result is null and the key has no entry in the map, no action is taken, as at (11).

Click here to view code image

// Before: {112=Norway, 999=UK, 190=null, 911=null}
etnMap.compute(112, (key, oVal) -> null);              // (7) null, removed
etnMap.compute(999, (key, oVal) -> “Uganda”);          // (8) Uganda, updated
etnMap.compute(190, (key, oVal) -> null);              // (9) null, removed
etnMap.compute(911, (key, oVal) -> “USA”);             // (10) USA, updated
etnMap.compute(100, (key, oVal) -> null);              // (11) null, no action
etnMap.compute(110, (key, oVal) -> “China”);           // (12) China, inserted
// After: {110=China, 999=Uganda, 911=USA}

The computeIfAbsent() method executes as follows:

  • If the key is associated with a null value or has no entry in the map, the remap-ping function is executed.
    • If the result is non-null, as at (16) and (18), this result is associated with the key.

Click here to view code image

// Before: {112=Norway, 999=UK, 190=null, 911=null}
etnMap.computeIfAbsent(112, key -> null);              // (13) Norway, no change
etnMap.computeIfAbsent(999, key -> “Uganda”);          // (14) UK, no change
etnMap.computeIfAbsent(190, key -> null);              // (15) null, no change
etnMap.computeIfAbsent(911, key -> “USA”);             // (16) USA, updated
etnMap.computeIfAbsent(100, key -> null);              // (17) null, no action
etnMap.computeIfAbsent(110, key -> “China”);           // (18) China, inserted
// After: {112=Norway, 110=China, 999=UK, 190=null, 911=USA}

The computeIfPresent() method executes as follows:

  • If the key is associated with a non-null value in the map, as at (19) and (20), the remapping two-arity function is executed.
    • If the result is null, then the entry with the key is removed, as at (19).
    • If the result is non-null, then the key is associated with the result, as at (20).

Click here to view code image

// Before: {112=Norway, 999=UK, 190=null, 911=null}
etnMap.computeIfPresent(112, (key, oVal) -> null);      // (19) null, removed
etnMap.computeIfPresent(999, (key, oVal) -> “Uganda”);  // (20) Uganda, updated
etnMap.computeIfPresent(190, (key, oVal) -> null);      // (21) null, no change
etnMap.computeIfPresent(911, (key, oVal) -> “USA”);     // (22) null, no change
etnMap.computeIfPresent(100, (key, oVal) -> null);      // (23) null, no action
etnMap.computeIfPresent(110, (key, oVal) -> “China”);   // (24) null, no action
// After: {999=Uganda, 190=null, 911=null}

Leave a Reply

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