Creo que es, al menos en parte, para que pueda combinar containsKeyy geten una sola llamada. Si el mapa puede contener nulos, no hay forma de saber si getestá devolviendo un valor nulo porque no había una clave para ese valor, o simplemente porque el valor era nulo.
¿Por que eso es un problema? Porque no hay una forma segura de hacerlo tú mismo. Toma el siguiente código:
if (m.containsKey(k)) {
return m.get(k);
} else {
throw new KeyNotPresentException();
}
Como mes un mapa concurrente, la clave k puede eliminarse entre las llamadas containsKeyy get, lo que hace que este fragmento devuelva un valor nulo que nunca estuvo en la tabla, en lugar de lo deseado KeyNotPresentException.
Normalmente lo resolverías sincronizando, pero con un mapa concurrente que, por supuesto, no funcionará. Por lo tanto, la firma de gettuvo que cambiar, y la única forma de hacerlo de una manera compatible con versiones anteriores era evitar que el usuario inserte valores nulos en primer lugar, y continuar usándolo como un marcador de posición para "clave no encontrada".