无法使用 :: 运算符将新列表初始化为 Map 的值?

Unable to initialize new List as value of a Map with the :: Operator?

在处理纸牌游戏项目时,我试图创建一个新地图,同时已经有了一个我想用作 KeySet 的列表。 Map 必须使用 Player 类型的 Keys,并且每个 Keys 都有一个由单个 List<Trick> 组成的 Value,Player 是一个 Interface 和 Trick - class.

最初我尝试使用我拥有的 List<Player> players 的 Stream,然后通过以下方式将其收集到 Map 中:

private Map<Player, List<Trick>> playerTricks = players.stream()
        .collect(Collectors.toMap(x -> x, ArrayList::new));

我的IDE,IntelliJ,但是不允许我使用这种格式,正如它所说的那样"Cannot resolve Constructor ArrayList"。

令我惊讶的是,当我删除 ::-Operator:

时 IDE 停止了抱怨
(Collectors.toMap(x -> x, x -> new ArrayList<Trick>()));

虽然我现在的代码没有异常,但我仍然不明白为什么范围解析运算符会产生这样的错误。如果有人能正确解释它,我将不胜感激。

P.S. 在搜索解决方案时,我发现了这个 Whosebug 线程:

Storing a new object as the value of a hashmap?

它确实涉及类似的问题,但并没有真正解决我面临的问题。

second parameter of Collectors.toMap 接受一个 Function,它接受流类型并将其映射到新的 Map 的值类型。

Function<? super T,? extends U> valueMapper

首先,:: 不像在 C++ 中那样被称为作用域解析运算符,尽管在 Java 中创建 方法引用 时它的功能有些相似.只是(简单地)"double-colon operator".

方法引用 ArrayList::newFunction<Player, List<Trick>> 不匹配,因为没有 ArrayList(Player) 构造函数。不能使用此方法参考。您试图忽略 Player 参数,但方法引用必须使用它。

当您将方法引用替换为 lambda 表达式 x -> new ArrayList<Trick>() 时,它确实匹配 Function<Player, List<Trick>>。您正在使用 x,它被隐式定义为 Player,而 lambda 表达式的类型是 List<Trick>,它匹配。您忽略了 lambda 表达式中的 Player x,甚至在它调用创建新的 ArrayList.

之前

您的 lambda 表达式 等同于方法引用,因为您的方法引用试图找到一个 ArrayList(Player) 构造函数,而 lambda 表达式采用 Player 并在仅显式调用无参数 ArrayList 构造函数时忽略它。