【问题标题】:HashMap returned by Maps.newHashMap vs new HashMapMaps.newHashMap 返回的 HashMap 与新的 HashMap
【发布时间】:2012-10-20 15:43:34
【问题描述】:

我第一次尝试番石榴,我发现它真的很棒。

我在 Spring jdbc 模板上执行了几个参数化检索查询。 DAO (AbstractDataAccessObject) 中的方法是这样的。这里没问题。

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;
}

问题来了:

当我使用

调用此方法时
getResultAsMap(query, new HashMap<String,Object>(ImmutableMap.of("gciList",gciList)));

效果很好。

但是当我这样做时

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

编译器不高兴说

The method getResultAsMap(String, Map&lt;String,Object&gt;) in the type AbstractDataAccessObject is not applicable for the arguments (String, HashMap&lt;String,List&lt;String&gt;&gt;)

我是不是做错了什么?或者是什么原因导致了此投诉?

【问题讨论】:

  • 可能你应该把 gciList 放在 Object => (Object)gciList 上,然后再把它作为参数
  • 正如 mykhaylo 所说,问题在于签名与类型参数不匹配 - 您期望 Map,但提供 Map> -将列表转换为对象是可行的,但更好的解决方案可能是使用通配符(如果您重用该方法),向辅助方法添加类型参数,或者只是修复签名以要求您实际获得的类型。跨度>
  • @mykhaylo 太好了。打字工作。和伟大的建议塞巴斯蒂安。我应该介绍一个类型参数。但是告诉我一件事,为什么 List 不能容纳在 Object 中?
  • @ArunManivannan 它不能那样工作,因为你会得到一个 Map ,你可以在其中添加任意对象,但是它应该只包含字符串列表!它应该适用于 Map - 因为这可以被分配一个 Map>...
  • @Sebastian 很好地解释了。非常感谢

标签: java spring collections guava


【解决方案1】:

这是类型推断失败。 Maps.newHashMap 是一个静态参数化方法。它允许您使用

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

而不是

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

让您不必输入两次&lt;String,Integer&gt;。在 Java 7 中,菱形运算符允许您使用

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

所以该方法是多余的。

要回答您的问题,只需使用new HashMap 版本,因为类型推断不适用于方法参数。 (您可以使用Maps.&lt;String,Object&gt;newHashMap(),但这违背了使用该方法的意义)

【讨论】:

【解决方案2】:

这里的问题是您的方法采用Map&lt;String, Object&gt;,但这实际上并不是您想要的。你想要一个MapString 键来任何 种值。那不是Map&lt;String, Object&gt;,是Map&lt;String, ?&gt;

【讨论】:

  • 感谢@ColinD 解释清楚。
【解决方案3】:

在此处添加迟到的答案:

在类型推断出现在 java 之前,大部分好处已经消失了。 (耶)但我想知道任何性能差异。这是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>();
  }

代码相同。

【讨论】:

  • @fordperfect,存在性能差异。我尝试向使用 guava 和 jdk 创建的地图添加 100 个对象,guava 需要 20-25 毫秒,而 jdk 需要 1 毫秒。
  • @hardeepthakur 考虑到一个是 jdk 本地的,而另一个是调用库,这本质上是有道理的。您正在执行额外的间接操作,但代码本身是相同的。正如我在答案中所说的那样,它存在的原因是由于在 java 8 之前缺乏类型推断
【解决方案4】:

更新:我误读了编译器错误 - 抱歉!随意删除我的答案!

“Map”的确切类型是什么 - 真的是 java.util.Map 和 HashMap 的确切类型 - 真的是 java.util.HashMap 吗?这里似乎有不匹配的地方。

原始“答案”:显然 Maps.newHashMap 返回 Map 接口的实现,这是未知的,但是 getResultAsMap 需要一个 HashMap (这是一个不寻常的要求)。 getResultAsMap 应该被重构以接受接口,而不是具体的实现。

【讨论】:

  • 不用担心塞巴斯汀。我检查并交叉检查。所有指向 java.util 包。除非 Guava 返回一个不实现 Map 接口的 HashMap,否则这应该可以工作。我检查了来源,它看起来确实不错。
  • @ArunManivannan:请参阅我上面的评论 - 在您的问题下方 - 问题是类型参数不匹配。
  • 谢谢@Sebastian。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-28
  • 2013-03-30
  • 2017-05-30
  • 2020-04-30
  • 1970-01-01
  • 2013-04-04
相关资源
最近更新 更多