![](/img/trans.png)
[英]Create only 1 list from a map where map value is list using JAVA 8 Streams
[英]Java Map with List value to list using streams?
我正在尝试使用流重写下面的方法,但我不确定最好的方法是什么? 如果我在entrySet()
的值上使用flatMap
,我会丢失对当前键的引用。
private List<String> asList(final Map<String, List<String>> map) {
final List<String> result = new ArrayList<>();
for (final Entry<String, List<String>> entry : map.entrySet()) {
final List<String> values = entry.getValue();
values.forEach(value -> result.add(String.format("%s-%s", entry.getKey(), value)));
}
return result;
}
我设法做的最好的事情如下:
return map.keySet().stream()
.flatMap(key -> map.get(key).stream()
.map(value -> new AbstractMap.SimpleEntry<>(key, value)))
.map(e -> String.format("%s-%s", e.getKey(), e.getValue()))
.collect(Collectors.toList());
有没有更简单的方法而无需创建新的Entry
对象?
stream 是一个值序列(可能是无序的/并行的)。 当您想将序列中的单个值 map 转换为某个其他值时,您可以使用map()
。 比如说,map“alturkovic”到“ALTURKOVIC”。 当您想将序列中的单个值 map 转换为 0、1 或许多其他值时,您可以使用flatMap()
。 因此为什么 flatMap lambda 需要将值转换为值的 stream。 因此,flatMap 可用于获取字符串列表的列表,并将其转换为仅包含字符串的 stream。
在这里,您希望将 map(单个键/值对)中的单个条目 map 转换为单个元素(描述它的字符串)。 1 值到 1 值。 这意味着flatMap 不合适。 您正在寻找的只是 map。
此外,您需要 key 和 value 来执行映射操作,因此keySet() 也不合适。 您正在寻找entrySet()
,它为您提供了一组所有 k/v 对,正是我们需要的。
这让我们:
map.entrySet().stream()
.map(e -> String.format("%s-%s", e.getKey(), e.getValue()))
.collect(Collectors.toList());
您的原始代码没有努力将 map (这是一个List<String>
)中的单个值视为单独的值; 您只需在整个考验中调用.toString()
即可。 这意味着生成的字符串看起来像[Hello, World]
给定的 map 值List.of("Hello", "World")
。 如果你不想要这个,你仍然不想要 flatmap,因为流也是同质的 - stream 中的值都是相同的,因此“key1 value1 value2 key2 valueA valueB”的 stream 不是什么你想要:
map.entrySet().stream()
.map(e -> String.format("%s-%s", e.getKey(), myPrint(e.getValue())))
.collect(Collectors.toList());
public static String myPrint(List<String> in) {
// write your own algorithm here
}
Stream API 不是替代 myPrint 方法的正确工具。
第三种选择是您想要涂抹 map; 您希望 mapvalue 的List<String>
中的每个字符串首先与键匹配(因此重新说明该键相当多),然后对此做一些事情。 现在flatMap是合适的 - 你首先想要一个 k/v 对的 stream ,然后对此做一些事情,每个元素现在都是同一种。 您要转动 map:
key1 = [value1, value2]
key2 = [value3, value4]
首先进入 stream:
key1:value1
key1:value2
key2:value3
key2:value4
并从那里拿走。 这会将 map 中的单个 k/v 条目分解为多个,因此需要平面映射:
return map.entrySet().stream()
.flatMap(e -> e.getValue().stream()
.map(v -> String.format("%s-%s", e.getKey(), v))
.collect(Collectors.toList());
从内到外,它将列表中属于单个 k/v 对的单个条目映射到字符串Key-SingleItemFromItsList
中。
将我的两美分添加到@rzwitserloot 的出色答案中。 在他的回答中已经解释了平面图和 map。
List<String> resultLists = myMap.entrySet().stream()
.flatMap(mapEntry -> printEntries(mapEntry.getKey(),mapEntry.getValue())).collect(Collectors.toList());
System.out.println(resultLists);
将其拆分为单独的方法可提供良好的可读性 IMO,
private static Stream<String> printEntries(String key, List<String> values) {
return values.stream().map(val -> String.format("%s-%s",key,val));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.