【问题标题】:Java Map computeIfAbsent issueJava Map computeIfAbsent 问题
【发布时间】:2018-12-19 07:27:04
【问题描述】:

所以我对 Java 的 Map computeIfAbsent(使用 java8)方法感到好奇,我希望有人能告诉我为什么会这样,因为我无法真正理解该问题背后的逻辑。

所以,我有一个带键的 Map(显然),值是一个列表,当尚未设置键时,我使用 computeIfAbsent 创建一个新列表。现在,当我使用整数作为键时,我可以使用以下内容:

List<Object> list = map.computeIfAbsent(1, ArrayList::new);

但是当我使用字符串作为键尝试使用时

List<Object> list = map.computeIfAbsent("key", ArrayList::new);

我收到The method computeIfAbsent(String, Function&lt;? super String,? extends List&lt;Object&gt;&gt;) in the type Map&lt;String,List&lt;Object&gt;&gt; is not applicable for the arguments (String, ArrayList::new) 的错误。只是缺少实现吗?使用 String 键,我必须使用类似的方法,然后再次工作。

List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>());

也许有人可以启发我。谢谢:)

【问题讨论】:

  • 附带说明,Guava 的 MultiMap 已经实现了您正在寻找的内容。
  • 为了清楚问题,值得一提的是代码中使用的map的类型
  • 我很确定这是重复的,但很难找到:-/
  • 啊,它是:stackoverflow.com/q/35296734/3182664 - 有任何反对将这个作为另一个副本关闭吗?

标签: java java-8 functional-programming


【解决方案1】:

映射函数 - Function&lt;? super K, ? extends V&gt; mappingFunction - 将键映射到值,因此当键为 Integer 时,ArrayList::new 有效,因为 ArrayList 有一个采用 int(初始容量)的构造函数。另一方面,它没有采用String 的构造函数。

由于密钥可能不应该影响ArrayList 的初始容量,因此您不应该在此处使用方法引用(在这两种情况下)。使用 lambda 表达式。

为了更清楚:

List<Object> list = map.computeIfAbsent(1, ArrayList::new);

行为类似于:

List<Object> list = map.computeIfAbsent(1, k -> new ArrayList<>(k));

因此它将创建一个初始容量为 1 的 ArrayList

另一方面:

List<Object> list = map.computeIfAbsent("key", ArrayList::new);

行为类似于:

List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));

其中kString,所以它没有通过编译。

【讨论】:

  • 更具体地说,1 -&gt; ArrayList::new 实际上并没有生成插入值 1 的列表。
  • 那么当使用ArrayList::new 时,给定的键被插入到列表中?在我的示例中,我已经有一个值为 1 的列表?
  • @chrylis OP 是否期望这种行为(1 被插入到列表中)?我没有看到问题中提到的。
  • @Fusel 无论哪种方式,键都将成为列表的一部分,但是在两种情况下(整数和字符串键)都使用 lambda 表达式是正确的。不,ListList&lt;String&gt; 没有区别,因为密钥没有添加到 List,它被传递给 ArrayList 构造函数(这对字符串不起作用,因为 ArrayList 没有接受字符串)。
  • @Fussel 如果将1 替换为 10 亿,则可能会出现内存错误,因为 Java 将尝试分配一个能够存储 10 亿个元素的数组。请注意容量!=实际元素。一个空的ArrayList 可以根据容量消耗任意数量的内存。
【解决方案2】:

你的第二次尝试

List<Object> list = map.computeIfAbsent("key", ArrayList::new);

实际上等于

List<Object> list = map.computeIfAbsent("key", k -> new ArrayList<>(k));

并且由于ArrayList 没有将字符串作为参数的构造函数,因此它不起作用。第一个示例的工作原理是创建一个包含一个元素的列表。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-06-19
    • 1970-01-01
    • 1970-01-01
    • 2022-12-03
    • 1970-01-01
    • 2014-11-19
    • 1970-01-01
    • 2018-11-14
    相关资源
    最近更新 更多