web-dev-qa-db-fra.com

HashMap renvoyé par Maps.newHashMap vs new HashMap

J'essaie Goyave pour la première fois et je le trouve vraiment génial.

J'exécute quelques requêtes de récupération paramétrées sur un modèle Spring jdbc. La méthode dans le DAO (AbstractDataAccessObject) va comme ceci. Pas de problème ici.

public Map<String,Object> getResultAsMap(String sql, Map<String,Object> parameters) {
    try {
        return jdbcTemplate.queryForMap(sql, parameters);
    } catch (EmptyResultDataAccessException e) {
        //Ignore if no data found for this query
        logger.error(e.getMessage(), e);

    }
    return null;
}

Voici le problème:

Quand j'appelle cette méthode en utilisant

getResultAsMap(query, new HashMap<String,Object>(ImmutableMap.of("gciList",gciList)));

cela fonctionne très bien.

Mais quand je fais ça

getResultAsMap(query, Maps.newHashMap(ImmutableMap.of("gciList",gciList)));

le compilateur s'énerve en disant

The method getResultAsMap(String, Map<String,Object>) in the type AbstractDataAccessObject is not applicable for the arguments (String, HashMap<String,List<String>>)

Est-ce que je fais quelque chose de mal ou quelle pourrait être la raison de cette plainte?

14
Arun Manivannan

L'inférence de type échoue. Maps.newHashMap est une méthode paramétrée statique. Cela vous permet d'utiliser

Map<String,Integer> map = Maps.newHashMap()

au lieu de

Map<String,Integer> map = new HashMap<String,Integer>()

vous évitant d'avoir à taper <String,Integer> deux fois. En Java 7, l’opérateur losange vous permet d’utiliser

Map<String,Integer> map = new HashMap<>()

la méthode est alors redondante.

Pour répondre à votre question, utilisez simplement la version new HashMap, car l’inférence de type ne fonctionne pas pour les paramètres de méthode. (Vous pouvez utiliser Maps.<String,Object>newHashMap() mais cela annule le point d'utiliser la méthode)

30
artbristol

Le problème ici est que votre méthode prend Map<String, Object>, mais ce n'est pas ce que vous voulez réellement. Vous voulez une clé Map of String à any kind of values. Ce n'est pas Map<String, Object>, c'est Map<String, ?>.

3
ColinD

Ajouter une réponse tardive ici:

La plupart des avantages ont disparu avant que l'inférence de type ne parvienne à Java. (yay) mais je m'interrogeais sur les différences de performances. Voici le code pour google.common.collect.maps

  /**
   * Creates a <i>mutable</i>, empty {@code HashMap} instance.
   *
   * <p><b>Note:</b> if mutability is not required, use {@link
   * ImmutableMap#of()} instead.
   *
   * <p><b>Note:</b> if {@code K} is an {@code enum} type, use {@link
   * #newEnumMap} instead.
   *
   * @return a new, empty {@code HashMap}
   */
  public static <K, V> HashMap<K, V> newHashMap() {
    return new HashMap<K, V>();
  }

C'est le même code.

2
ford prefect

Mise à jour: j'ai mal interprété l'erreur du compilateur - désolé! N'hésitez pas à supprimer ma réponse!

Quel est le type exact de "Carte" - s'agit-il vraiment de Java.util.Map et du type exact de HashMap - s'agit-il vraiment de Java.util.HashMap? Il semble y avoir une inadéquation ici.

"Réponse" d'origine: il est évident que Maps.newHashMap renvoie une implémentation de l'interface Map inconnue. Cependant, getResultAsMap requiert un HashMap (exigence inhabituelle). getResultAsMap doit être modifié pour accepter l'interface plutôt qu'une implémentation concrète.

0
Sebastian