以有效的方式从地图条目中获取公共值

Aka*_*rma -1 java functional-programming hashmap java-8 java-stream

假设有如下图所示:

    Map<String, List<String>> myMap =     
     {   
        k1: [ v1, v2, v3, v3],  
        k2: [ v1, v2],  
        k3: [ v1, v2, v6, v7]
      }
Run Code Online (Sandbox Code Playgroud)

我想找到所有键通用的值。

 List<String> commonValues = {v1,v2}
Run Code Online (Sandbox Code Playgroud)

我想了解使用 java 8 的有效方法。我可以在 java 5 中使用 for 循环实现相同的效果,但我确信 Java 8 有更好的方法来做到这一点。

Lin*_*ica 6

你可以使用这样的东西:

List<String> commonValues = myMap.values().stream()
    .reduce((a, b) -> {
        a.retainAll(b);
        return a;
    })
    .orElse(Collections.emptyList());
Run Code Online (Sandbox Code Playgroud)

从文档retainAll

仅保留此集合中包含在指定集合中的元素(可选操作)。换句话说,从该集合中删除所有未包含在指定集合中的元素。

如果您正在使用不可变的多个线程或集合:

List<String> commonValues = myMap.values().stream()
    .reduce((a, b) -> {
        List<String> c = new ArrayList<>(a);
        c.retainAll(b);
        return c;
    })
    .orElse(Collections.emptyList());
Run Code Online (Sandbox Code Playgroud)

尽管此解决方案每次迭代都会创建一个新副本。

另一种方式会更hacky:

List<String> commonValues = myMap.values().stream()
    .reduce(null, (a, b) -> {
        if(a == null) return new ArrayList<>(b);
        a.retainAll(b);
        return a;
    });
Run Code Online (Sandbox Code Playgroud)

但这一次,commonValues可能是null,所以你必须检查一下

  • 我相信这会为提供的示例数据 OP 引发“UnsupportedOperationException”。 (2认同)
  • @sleepToken 由于 OP 没有提供有效的 Java 代码,我们不知道集合将具有哪种实际类型。但是使用带有修改输入的函数的归约无论如何都会被破坏。特别是对于 Stream API,它要求函数是关联的,因此它甚至不允许预测哪些输入集合最终将被修改(如果它们支持修改)…… (2认同)