如何避免在向ArrayList添加元素时出现“lambda表达式中参数类型不兼容”的问题?

13

我有以下的代码

public static List<Integer> topKFrequent(int[] nums, int k) {
  List<Integer> myList = new ArrayList<>();
  HashMap<Integer, Integer> map = new HashMap<>();

  for (int n : nums) {
    if (!map.containsKey(n)) map.put(n, 1);
    else map.put(n, map.get(n) + 1);
  }

  map.entrySet().stream()
    .sorted(Map.Entry.<Integer, Integer>comparingByValue().reversed())
    .limit(k)
    .forEach((key, value) -> myList.add(key));

  return myList;
}

forEach 抛出错误。

Error:(20, 16) java: incompatible types: incompatible parameter types in lambda expression
我该如何修复/避免这个错误?我不太确定如何应用这里解释问题的答案:Lambda Expression and generic method 编辑:
根据答案,更正方法是将forEach中的lambda替换为:
.forEach((entry) -> myList.add(entry.getKey()));

遗憾的是,Java不允许元组解包。 - Boris the Spider
请提供兼容的参数,以避免出现问题。题目起得不好,答案显然是“不要提供不兼容的参数”。 - Boris the Spider
1
@Boris the Spider:但编写一个将BiConsumer<K,V>转换为Consumer<Map.Entry<K,V>>的实用方法是微不足道的... - Holger
1
@Boris the Spider: 更糟糕的是,Java 没有元组... - Holger
1
@AR7:注意,对于你的第一个循环,你可以使用已接受答案的流解决方案,但是当你使用循环时,你可以用map.merge(n, 1, Integer::sum);替换if (!map.containsKey(n)) map.put(n, 1); else map.put(n, map.get(n) + 1);。因此,不仅有Stream API,Collection API也有许多有用的新方法。 - Holger
显示剩余2条评论
2个回答

6

entrySet()返回一个由Pair<K, V>组成的集合。

forEach()方法的lambda表达式的参数类型是该集合中的单个元素,而不是两个整数参数。


5
你正在使用类似于Java7的方式进行操作。在forEach内修改外部数据结构不是Streams API的正确使用方式。Streams API文档特别警告了这样的使用,见java.util.stream包概述中的副作用一节。
与其在forEach内附加到列表或映射中,不如使用collect
import static java.util.Comparator.reverseOrder;
import static java.util.Map.Entry.comparingByValue;
import static java.util.stream.Collectors.counting;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;


public static List<Integer> topKFrequent(int[] nums, int k) {
    Map<Integer, Long> freq = Arrays.stream(nums).boxed()
            .collect(groupingBy(x->x, counting()));

    return freq.entrySet()
            .stream()
            .sorted(comparingByValue(reverseOrder()))
            .limit(k)
            .map(Map.Entry::getKey)
            .collect(toList());
}

2
啊,好的,这很酷。我已经有两年没写Java了,所以现在代码有点混乱。在流中不要有副作用是有道理的,但我还不太确定自己在做什么。 - m0meni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接