簡體   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