Codectionary / Developer documentation / Java

Grouping Values with computeIfAbsent

Create a missing map value on demand before adding an item to it.

What it is and why to use it

A map of lists often needs an empty list the first time a key appears. computeIfAbsent combines looking up the key and calculating a value when there is no current non-null mapping. This removes repeated containsKey and put boilerplate for grouping items.

How it works

The mapping function receives the key and returns the new value. A non-null result is stored and returned; returning null creates no mapping. If a non-null value already exists, the function is not called and that existing value is returned. Here the returned list receives the next learner.

Common mistakes and limitations

The general Map contract does not promise atomic concurrent execution. Even when a concurrent map creates a list atomically, an ArrayList stored inside it is not thereby thread-safe. Avoid changing the map itself inside the mapping function.

Try it and keep learning

Save the complete example below as Main.java. With a JDK supporting Java 17, compile using javac --release 17 Main.java, then run java Main from the same directory. These examples need only the standard library and fixed input; they do not require packages, files or network access.

Syntax

groups.computeIfAbsent(key, ignored -> new ArrayList<>()).add(value);

Examples

Grouping Values with computeIfAbsent

Complete Main.java example — Java 17 or later, without preview features.

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class Main {
  public static void main(String[] args) {
    Map<String, List<String>> groups = new LinkedHashMap<>();
    groups.computeIfAbsent("Java", key -> new ArrayList<>()).add("John");
    groups.computeIfAbsent("Java", key -> new ArrayList<>()).add("James");
    System.out.println(groups);
  }
}
  1. The first lookup finds no Java value, creates an ArrayList, stores it and adds John.
  2. The second lookup returns that same list and adds James without replacing John.
  3. The map prints one key with two learners. This pattern works for organising records by category during a single-threaded import.
  4. Expected output: {Java=[John, James]}

Best practices

  • Keep mapping functions small.
  • Choose concurrency-safe values as well as a concurrency-safe map when sharing state.

Runtime & versions

Java Virtual Machine. Feature availability depends on the language and runtime version used by your project; consult the official reference below.

Java Language Specification

Specifications & further reading