当分类器 returns 一个列表时,groupingBy 是如何工作的?

How does groupingBy work when classifier returns a List?

考虑this SO answer

我有几个问题:

  1. 它是如何工作的? groupingBy() 是否检查 classifier 的返回值是否为 List 并比较每一项?对我来说,这听起来不像是典型的 Java 函数
  2. List如何包含不同的变量类型?编译器是否将其视为 List<Object>?
  3. 使用List是否反模式?

这里发生的是分类器返回的值使用 equals() 方法进行比较,在指定 List 的情况下:

List.equals():

Returns true if and only if the specified object is also a list, both lists have the same size, and all corresponding pairs of elements in the two lists are equal.

实际上,比较和等于调用是由底层 Map 实现完成的。

你的第二个问题

How can List contain different variable types? Does the compiler treat it like a List<Object>?

不完全是,它是原始类型,请参阅 Java difference between List and List<Object> 对于一些差异。

关于你的第三个问题,

Is it anti-pattern to use List?

这里回答了这个问题: ArrayList as key in HashMap

总结:这是有风险的,因为通常使用可变类型作为键。 hashCode 在插入 HashMap 后不得更改,这意味着列表本身或列表中的任何项目都不能以可能更改 hashCode()equals().

正如绿巨人所说,这里绝对没有魔法。 Listequals 方法进行比较,就像任何其他对象一样。

要回答您的第二个问题,可以使用泛型控制列表中项目的类型。太糟糕了,他们实际上在您链接到的答案中使用了 原始类型。应该用 List<?> 代替,但 List<Object> 也可以。

通常,列表实现的底层数组使用 Object[](至少 ArrayList 是这种情况)。

一个List<Object>只能包含Object个实例,但是你猜怎么着,Java语言中的所有对象都是Object,所以这个列表可以包含任何对象.

不变性

映射的键(在本例中 List不可变 很重要。典型的 Map 的工作方式是,它依赖于未更改的键。幸运的是,链接 post 的作者使用了 List::of,其中 returns 是一个 不可修改的 列表。

相关:Are mutable hashmap keys a dangerous practice?


链接 post 的作者使用 List 作为键,他在其中存储了用作分类器的字段。我会提出一个使用列表的替代解决方案,以便 select 多个字段用作分类器。我会创建一个 record 来代替创建分类器的意图:record AgeAndNameClassifier(int age, String name) { } 然后分组依据:groupingBy(item -> new AgeAndNameClassifier(item.getAge(), item.getName())...