这是我在直播中的第一个方法。我正在尝试自己学习它,但由于它是一种新的编程风格,我遇到了困难。
以下方法有一个
Map<Long, Ingredient>
参数(Ingredient
具有 String 属性 name
)。
我想返回一个倒置的
Map<String, Long>
(字符串是类的属性“名称”Ingredient
)。
public static Map<String, Long> focusOnNameAndInvert(Map<Long, Ingredient> articles) {
ArrayList<String> nameList = new ArrayList<>(articles.values().stream().map(Ingredient::getName).collect(Collectors.toList()));
ArrayList<Long> keyList = new ArrayList<>(articles.keySet());
Map<String, Long> nameAndInvertedMap = new HashMap<>();
for (int i = 0; i<nameList.size(); i++){
nameAndInvertedMap.put(nameList.get(i), keyList.get(i));
}
return nameAndInvertedMap;
}
初始化
<>
右侧的 HashMap
带有红色下划线,并显示 “无法推断参数”(使用 IntelliJ)
public static Map<String, Long> focusOnNameAndInvert(Map<Long, Ingredient> articles) {
Map<String, Long> nameAndInvertedMap = new HashMap<>(
articles.values().stream().map(Ingredient::getName),
articles.keySet().stream().map(articles::get));
return nameAndInvertedMap;
}
为什么这没有按我预期的方式工作,我该如何解决它?
您的方法实际上并没有达到您希望的效果。从编译器错误中可以看出,没有
HashMap
构造函数接受 List
键和 List
值。此外,即使确实如此,您也会流式传输给定的Map
(两次),然后尝试交换不同流中的键和值,最后甚至不收集流的值。流是延迟评估操作的管道,如果您不添加终端操作,它们甚至不会被执行。
这里有一个 Oracle 官方教程,很好地总结了流的概念及其工作原理:
https://docs.oracle.com/javase/tutorial/collections/streams/parallelism.html#laziness
您可以通过流式传输给定映射的条目来编写您的方法,然后使用
collect(Collectors.toMap())
终端操作收集它们,其中每个 Ingredient
的名称映射为键,而长键作为它们的值。
public static Map<String, Long> focusOnNameAndInvert(Map<Long, Ingredient> articles) {
return articles.entrySet().stream()
.collect(Collectors.toMap(entry -> entry.getValue().getName(), entry -> entry.getKey()));
}
请注意,如果有多个键(即您的情况下有重复的成分名称),则使用方法
toMap()
的 2 个参数版本收集条目将不起作用。该方法的 3 个参数版本应该是首选,因为它允许处理冲突键的情况(多个相同的键映射不同的值)。可能的实现可能是:丢弃一个值而不是另一个值,对这些值求和等等。
这是一种可能的实现,其中仅维护两个值之一。
public static Map<String, Long> focusOnNameAndInvert(Map<Long, Ingredient> articles) {
return articles.entrySet().stream()
.collect(Collectors.toMap(entry -> entry.getValue().getName(), entry -> entry.getKey(), (longVal1, longVal2) -> longVal1));
}
您的直播不正确。应该是这样的:
public static Map<String, Long> focusOnNameAndInvert(Map<Long, Ingredient> articles) {
return articles.entrySet().stream()
.collect(Collectors.toMap(entry -> entry.getValue().getName(), Map.Entry::getKey));
}