Understanding 'computeIfAbsent' and 'computeIfPresent' in Java's HashMap

Aman WalkeAman Walke
3 min read

👋 Introduction

Java’s HashMap is one of the most commonly used data structures for storing key-value pairs. With the introduction of Java 8, several new methods were added to the Map interface to make operations more expressive and efficient — two such methods are computeIfAbsent and computeIfPresent.

In this blog post, we will explore what these methods do, how they differ, and when to use them — all with clear examples.

📌 Why computeIfAbsent and computeIfPresent?

Before Java 8, updating or initializing a value in a map required verbose code:

if (map.get(key) == null) { // check if value against a key is present
    map.put(key, new ArrayList<>());
}
map.get(key).add(value);

This is a common pattern — initialize a value if it doesn’t exist, then operate on it. Java 8 introduced computeIfAbsent and computIfPresent to simplify such patterns.

🧠 computeIfAbsent

Definition:

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

Purpose: If the key is not already associated with a value (or is null), compute a value using provided function and insert it into the map.

✅ Use Case

When you want to lazily initialize a value for a key if it’s not already present.

🧪 Example

Map<String, List<String>> map = new HashMap<>();

map.computeIfAbsent("fruits", k -> new ArrayList<>()).add("apple");
map.computeIfAbsent("fruits", k -> new ArrayList<>()).add("banana");
map.computeIfAbsent("vegetables", k -> new ArrayList<>()).add("carrot");

System.out.println(map);
// Output: {fruits=[apple, banana], vegetables=[carrot]}
  • "fruits" wasn’t in the map initially, so it was added with a new ArrayList and "apple" was added.

  • The second call finds the existing list and just adds "banana" to it.

🧠 computeIfPresent

Definition:

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

Purpose: If the key is already associated with a non-null value, compute a new value for it using the provided remapping function.

✅ Use Case

When you want to modify a value only if the key exists in the map.

🧪 Example

Map<String, Integer> stock = new HashMap<>();
stock.put("pen", 10);
stock.put("pencil", 0);

stock.computeIfPresent("pen", (k, v) -> v - 1); // Reduce pen stock
stock.computeIfPresent("pencil", (k, v) -> v - 1); // Still computed
stock.computeIfPresent("eraser", (k, v) -> 5); // Not present, won’t compute

System.out.println(stock);
// Output: {pen=9, pencil=-1}
  • "pen" exists, so we reduce the count by 1.

  • "pencil" exists with value 0, still gets computed to -1.

  • "eraser" is absent — no computation occurs.

⚖️ Key Differences

FeaturecomputeIfAbsentcomputeIfPresent
Checks forKey not present or value is nullKey present and value is not null
Typical useLazy initializationConditional update
SignatureFunction<K, V>BiFunction<K, V, V>

⚠️ Things to Watch Out For

  1. Null values: If your map contains keys with null values, computeIfAbsent treats it as absent, but computeIfPresent ignores them.

  2. Concurrency: These methods are not thread-safe for HashMap. Use ConcurrentHashMap if needed in multi-threaded environments.

  3. Return value: Both methods return the new (or existing) value. If computation returns null, the mapping is removed.

🔚 Conclusion

computeIfAbsent and computeIfPresent are powerful tools that help you write cleaner, more readable code when working with maps. They reduce boilerplate and make your intentions more explicit.

Next time you find yourself checking for a key’s presence or absence before modifying a HashMap, reach for these handy methods!

0
Subscribe to my newsletter

Read articles from Aman Walke directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Aman Walke
Aman Walke

I'm a tech enthusiast who loves building backend systems that just work — clean, scalable, and efficient. I've worked with microservices, Spring Boot, Azure, and APIs, and I enjoy digging into root causes and making systems better. Whether it's writing clean code, reviewing it, or managing deployments with DevOps tools, I'm always up for the challenge. I like working in collaborative environments where I can learn, share, and grow alongside smart people.