Collectors.toMap() keyMapper——更简洁的表达方式?
Posted
技术标签:
【中文标题】Collectors.toMap() keyMapper——更简洁的表达方式?【英文标题】:Collectors.toMap() keyMapper -- more succinct expression? 【发布时间】:2013-10-15 19:11:56 【问题描述】:我正在尝试为以下Collectors.toMap()
调用中的“keyMapper”函数参数提出一个更简洁的表达式:
List<Person> roster = ...;
Map<String, Person> map =
roster
.stream()
.collect(
Collectors.toMap(
new Function<Person, String>()
public String apply(Person p) return p.getLast();
,
Function.<Person>identity()));
似乎我应该能够使用 lambda 表达式内联它,但我想不出一个可以编译的。 (我对 lambdas 很陌生,所以这不足为奇。)
谢谢。
--> 更新:
如已接受的答案中所述
Person::getLast
是我一直在寻找的,也是我尝试过的。然而,Eclipse 4.3 的 BETA_8 nightly build 是个问题——它标记为错误。从命令行编译时(我应该在发布之前完成),它起作用了。因此,是时候向 eclipse.org 提交错误了。
谢谢。
【问题讨论】:
请注意,静态导入 Collectors.toMap 会使表达式更短,不过 NetBeans 似乎并没有为我导入这些。 刚刚偶然发现了这个问题。你的问题不仅是Eclipse 4.3,还有u112之前的JDK 8,也有类似的问题。 HTH。 【参考方案1】:我们也可以使用可选的合并功能以防相同的键冲突。 例如,如果两个或多个人具有相同的 getLast() 值,我们可以指定如何合并这些值。如果我们不这样做,我们可能会得到 IllegalStateException。 这是实现此目的的示例...
Map<String, Person> map =
roster
.stream()
.collect(
Collectors.toMap(p -> p.getLast(),
p -> p,
(person1, person2) -> person1+";"+person2)
);
【讨论】:
对不起,这是什么意思?(person1, person2) -> person1+";"+person2)
如果映射的键包含重复项(根据 Object.equals(Object)),则将值映射函数应用于每个相等的元素,并使用提供的合并函数合并结果。请参考链接docs.oracle.com/javase/8/docs/api/java/util/stream/…【参考方案2】:
您可以使用 lambda:
Collectors.toMap(p -> p.getLast(), Function.identity())
或者,更简洁地说,您可以使用 method reference 和 ::
:
Collectors.toMap(Person::getLast, Function.identity())
您可以简单地使用等效的 lambda,而不是 Function.identity
:
Collectors.toMap(Person::getLast, p -> p)
如果您使用 Netbeans,只要匿名类可以被 lambda 替换,您就会得到提示。
【讨论】:
您可以通过删除括号来使表达式更短,因为单个参数不需要括号,即Collectors.toMap(Person::getLast, p -> p)
。
我也很确定身份函数的类型参数不是必需的,因为它可以被推断出来。 Collectors.toMap(Person::getLast, Function.identity())
@GuiSim 我认为现在确实如此 - 这是 Java 8 早期版本中的一个错误。
呵呵,好像 p -> p 被优化了,没有新建编译匿名类。我猜它在内部使用 Function.identity(),而不是创建一个无用的类。
重要的警告!如果您的 List 包含空值,您将在此处遇到异常,因为 Collectors.toMap 是如何实现的,即使具有空值的映射通常是完全可以接受的。当然,在这种情况下,您在访问 Person::getLast 时无论如何都会得到 NPE,但在许多其他情况下,您的密钥可能组合方式不同,但您仍然会遇到异常。见***.com/questions/24630963/…【参考方案3】:
List<Person> roster = ...;
Map<String, Person> map =
roster
.stream()
.collect(
Collectors.toMap(p -> p.getLast(), p -> p)
);
这将是翻译,但我没有运行它或使用 API。您很可能可以将 p -> p 替换为 Function.identity()。并静态导入 toMap(...)
【讨论】:
有没有办法在 List以上是关于Collectors.toMap() keyMapper——更简洁的表达方式?的主要内容,如果未能解决你的问题,请参考以下文章
List 转 Map 之 Collectors.toMap()
java8的stream中Collectors.toMap空指针问题