繁体   English   中英

Java Map 与列表值使用流列出?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM