Reduce/Collect `List<Map<String, Set<String>` 到 `Map<String, Set<String>>`

Reduce/Collect `List<Map<String, Set<String>` to `Map<String, Set<String>>`

List 上执行 parallelStream() 后,我得到了 List<Map<String, Set<String>。我想将其统一为 Map<String, Set<String>>(这只会在 MapList 中保持唯一性)。

我不熟悉 collectreduce 函数,所以没有什么可以继续的。

现有代码:

private val TYPES = listOf("string", "integer")

private fun getLinesOfEachTypeAcrossMultipleFiles(files: List<File>): Map<String, Set<String>> {
  return files
    .parallelStream()
    .map { file ->
      TYPES.associate {
        it to getRelevantTypeLinesFromFile(file)
      }
    }
// Converted into a Stream<String, Set<String>>
// .reduce() / collect() ?
}

private fun getRelevantTypeLinesFromFile(it: File): Set<String> {
  // Sample code
  return setOf()
}

如果您正在寻找等效的 Java 代码,您可以使用 flatMap 流式传输所有条目,然后将它们收集为具有合并功能的地图:

Map<String, Set<String>> some(List<Map<String, Set<String>>> listOfMap) {
    return listOfMap.stream()
            .flatMap(a -> a.entrySet().stream())
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue,
                    (s1, s2) -> {
                        s1.addAll(s2);
                        return s1;
                    }));
}

我想出并实施了一个使用 fold 运算符(而不是 reducecollect)的特定于 Kotlin 的解决方案:

private val TYPES = listOf("string", "integer")

private fun getLinesOfEachTypeAcrossMultipleFiles(files: List<File>): Map<String, Set<String>> {
  return files
    .map { file ->
      TYPES.associate { it to getRelevantTypeLinesFromFile(file) }
    }

    .fold(mutableMapOf<String, MutableSet<String>>()) { acc, map ->
      acc.apply {
        map.forEach { key, value ->
          acc.getOrPut(key) { mutableSetOf() }.addAll(value)
        }
      }
    }
}

private fun getRelevantTypeLinesFromFile(it: File): Set<String> {
  // Sample code
  return setOf()
}

使用 fold 的一个好处是我们不需要将数据类型从 Map 更改为 MutableMap 以及将 Set 更改为 MutableSet.