La mejor manera de crear un mapa vacío en Java

117

Necesito crear un mapa vacío.

if (fileParameters == null)
    fileParameters = (HashMap<String, String>) Collections.EMPTY_MAP;

El problema es que el código anterior produce esta advertencia: Tipo de seguridad: Transmitir sin marcar de Map a HashMap

¿Cuál es la mejor forma de crear este mapa vacío?

JorgeO
fuente
¿Cuál es su tipo declarado para fileParameters?
jjnguy
Probablemente también obtendrá una ClassCastException.
Tom Hawtin - tackline
1
fileParameters debe ser un mapa y no un HashMap.
Steve Kuo

Respuestas:

241

1) Si el mapa puede ser inmutable:

Collections.emptyMap()

// or, in some cases:
Collections.<String, String>emptyMap()

Tendrá que usar este último a veces cuando el compilador no pueda determinar automáticamente qué tipo de mapa se necesita (esto se llama inferencia de tipo ). Por ejemplo, considere un método declarado así:

public void foobar(Map<String, String> map){ ... }

Al pasar el Mapa vacío directamente a él, debe ser explícito sobre el tipo:

foobar(Collections.emptyMap());                 // doesn't compile
foobar(Collections.<String, String>emptyMap()); // works fine

2) Si necesita poder modificar el Mapa, por ejemplo:

new HashMap<String, String>()

(como señaló tehblanx )


Anexo : Si su proyecto utiliza Guayaba , tiene las siguientes alternativas:

1) Mapa inmutable:

ImmutableMap.of()
// or:
ImmutableMap.<String, String>of()

Por supuesto, no hay grandes beneficios aquí en comparación con Collections.emptyMap(). Desde el Javadoc :

Este mapa se comporta y funciona de manera comparable Collections.emptyMap()y es preferible principalmente por la coherencia y el mantenimiento de su código.

2) Mapa que puedes modificar:

Maps.newHashMap()
// or:
Maps.<String, String>newHashMap()

Mapscontiene métodos de fábrica similares para crear instancias de otros tipos de mapas, como TreeMapo LinkedHashMap.


Actualización (2018) : en Java 9 o posterior, el código más corto para crear un mapa vacío inmutable es:

Map.of()

... utilizando los nuevos métodos de fábrica de conveniencia de JEP 269 . 😎

Jonik
fuente
En la mayoría de los casos, la inferencia de tipos funciona (es decir, map = Collections.emptyMap () funciona)
Sébastien RoccaSerra
Si cierto. Edité la respuesta para que fuera un poco más completa.
Jonik
16

Colecciones.emptyMap ()

basszero
fuente
El problema era que este mapa solo se puede aplicar a un objeto Map, no a un HashMap
JorgeO
7
Debería (generalmente) evitar declarar objetos de sus tipos específicos y usar la interfaz (o padre abstracto) en su lugar. Intente evitar "HashMap <String, String> foo;" y use "Map <String, String> foo;" en su lugar
TofuBeer
10

Si necesita una instancia de HashMap, la mejor manera es:

fileParameters = new HashMap<String,String>();

Dado que Map es una interfaz, debe elegir alguna clase que la instancia si desea crear una instancia vacía. HashMap parece tan bueno como cualquier otro, así que utilícelo.

AndreiM
fuente
7

O bien Collections.emptyMap(), o si la inferencia de tipos no funciona en su caso,
Collections.<String, String>emptyMap()

Peter Štibraný
fuente
2

Dado que en muchos casos se utiliza un mapa vacío para un diseño seguro para nulos, puede utilizar el nullToEmptymétodo de utilidad:

class MapUtils {

  static <K,V> Map<K,V> nullToEmpty(Map<K,V> map) {
    if (map != null) {
      return map;
    } else {
       return Collections.<K,V>emptyMap(); // or guava ImmutableMap.of()
    }
  }

}  

De manera similar para los conjuntos:

class SetUtils {

  static <T> Set<T> nullToEmpty(Set<T> set) {
    if (set != null) {
      return set;
    } else {
      return Collections.<T>emptySet();
    }
  }

}

y listas:

class ListUtils {

  static <T> List<T> nullToEmpty(List<T> list) {
    if (list != null) {
      return list;
    } else {
      return Collections.<T>emptyList();
    }
  }

}
Vitalii Fedorenko
fuente