get()
Look up a value by key, handle the null it returns for a miss, and avoid the wrong-key-type trap the compiler does not catch.
V get(Object key)- Added in Java Java 1.2
Parameters
| Parameter | Type | Description |
|---|---|---|
$key | Object | The key to look up. Typed as Object, so the compiler accepts any type. |
Return value
VThe value mapped to the key, or null if the map contains no mapping for it (or the key is mapped to null).
Errors
ClassCastException if the key's type is not compatible with the map (optional); NullPointerException if the key is null and the map does not permit null keys, such as Map.of, TreeMap with natural ordering or ConcurrentHashMap.
get returns the value stored for a key, or null if there is none. On a HashMap it takes constant time on average; on a TreeMap it takes logarithmic time and finds the key with compareTo or the map's comparator rather than equals.
The null you get back
A miss is not an exception, it is null. Forgetting that is the most common map bug. It often hides in an unboxing assignment:
Map<String, Integer> stock = new HashMap<>();
int qty = stock.get("SKU-2"); // NullPointerException: null cannot be unboxed to int
Handle the miss on purpose. Use getOrDefault when there is a sensible default, Optional.ofNullable(map.get(key)) when the caller should decide, or an explicit null check when a miss means "404 Not Found".
On maps that allow null values, null can also mean the key is present with a null value. If that difference matters, call containsKey. Better still, do not store nulls.
The parameter is Object
get takes Object, not K, so the compiler never complains about the key's type. A Map<Long, User> queried with an int boxes it to an Integer, and Integer.valueOf(42) is never equal to Long.valueOf(42). The lookup returns null every time. The same happens when you pass a String to a map keyed by UUID. When a lookup that "must" hit returns null, check the key's type first.
Other reasons for a surprising miss: the key class does not override equals and hashCode, the key object was changed after it was stored, or the strings differ in case or in leading and trailing spaces from user input.
On the back end
In-memory lookups are everywhere in a service: a product catalogue loaded at startup, a session token mapped to a user, a route table, per-request attributes. Turn the miss into the response it deserves (404, 401, or a default) at the point of the call, rather than letting a null travel through the code until it fails somewhere unrelated.
Example
When to use it
- Looking up a product in an in-memory catalogue and answering 404 when the SKU is unknown.
- Resolving a session token from a cookie to the signed-in user, or treating the request as anonymous.
- Finding the handler for a request path in a route table built at startup.
Frequently asked questions
Why does map.get return null when the key is there?
Usually the key you pass is not equal to the stored one: a different type (Integer versus Long, String versus UUID), different case or spaces, a key class without equals and hashCode, or a key object that was changed after it was put.
How do I tell a missing key from a null value?
Call containsKey(key). It returns true for a key mapped to null and false for a missing key, while get returns null in both cases.
Does Map.get throw an exception if the key is not found?
No, it returns null. It only throws for a null key on maps that do not allow null keys, such as Map.of, ConcurrentHashMap or a TreeMap with natural ordering.
More examples
Unboxing a missing value throws
Assigning the result to a boxed Integer is harmless, but assigning it to an int unboxes null and throws. getOrDefault gives the int a real value to unbox.
void main() {
Map<String, Integer> stock = new HashMap<>();
stock.put("SKU-1", 12);
Integer boxed = stock.get("SKU-2");
IO.println("boxed: " + boxed);
try {
int qty = stock.get("SKU-2");
IO.println(qty);
} catch (NullPointerException e) {
IO.println("NullPointerException when unboxing a missing value");
}
int safe = stock.getOrDefault("SKU-2", 0);
IO.println("safe: " + safe);
}
// Output:
// boxed: null
// NullPointerException when unboxing a missing value
// safe: 0A wrong key type compiles but never matches
IDs parsed as int and stored as long are a classic source of lookups that always miss. Converting the key to the map's key type fixes it.
void main() {
Map<Long, String> users = new HashMap<>();
users.put(42L, "ada");
int id = 42;
IO.println(users.get(id)); // boxed to Integer, never equal to a Long
IO.println(users.get((long) id)); // boxed to Long, matches
IO.println(Integer.valueOf(42).equals(Long.valueOf(42)));
}
// Output:
// null
// ada
// falseReturning Optional from a repository-style lookup
Wrapping the result in Optional at the boundary makes the possible miss visible in the method's type, so callers cannot forget it.
record Session(String user) {}
Map<String, Session> sessions = new HashMap<>();
Optional<Session> find(String token) {
return Optional.ofNullable(sessions.get(token));
}
void main() {
sessions.put("tok-123", new Session("ada"));
IO.println(find("tok-123").map(Session::user).orElse("anonymous"));
IO.println(find("tok-999").map(Session::user).orElse("anonymous"));
IO.println(find("tok-999").isPresent());
}
// Output:
// ada
// anonymous
// false
Discussion