Java 8 Map KeySet Stream 在收集器中无法按预期使用

use*_*512 3 java collections set java-8 java-stream

我一直在尝试学习 Java 8 的新功能接口特性,但在重构我之前编写的代码时遇到了一些困难。

作为测试用例的一部分,我想在 Map 结构中存储读取名称列表,以便检查这些读取是否已在后续代码部分“修复”。我正在从现有的 Map> 数据结构进行转换。我之所以要扁平化这个数据结构,是因为在后续的分析中不需要原始 Map 的外部“String”键(我用它来分离来自不同来源的数据,然后再将它们合并到中间数据中)。这是我原来的程序逻辑:

public class MyClass {
  private Map<String, Map<String, Short>> anchorLookup;
  ...
  public void CheckMissingAnchors(...){
    Map<String, Boolean> anchorfound = new HashMap<>();

    // My old logic used the foreach syntax to populate the "anchorfound" map
    for(String rg : anchorLookup.keySet()){
      for(String clone : anchorLookup.get(rg).keySet()){
        anchorfound.put(clone, false);
      }
    }
    ...
    // Does work to identify the read name in the file. If found, the boolean in the map
    // is set to "true." Afterwards, the program prints the "true" and "false" counts in 
    // the map
   }
}
Run Code Online (Sandbox Code Playgroud)

我尝试重构代码以使用函数式接口;但是,我从 IDE(运行 Java 1.8.0_05 的 Netbeans 8.0 Patch 2)收到错误:

public class MyClass {
  private Map<String, Map<String, Short>> anchorLookup;
  ...
  public void CheckMissingAnchors(...){

    Map<String, Boolean> anchorfound = anchorLookup.keySet()
      .stream()
      .map((s) -> anchorlookup.get(s).keySet())  // at this point I am expecting a 
      // Stream<Set<String>> which I thought could be "streamed" for the collector method
      // ; however, my IDE does not allow me to select the "stream()" method
      .sequential() // this still gives me a Stream<Set<String>>
      .collect(Collectors.toMap((s) -> s, (s) -> false);
      // I receive an error for the preceding method call, as Stream<Set<String>> cannot be 
      // converted to type String
    ...
   }
}
Run Code Online (Sandbox Code Playgroud)

有没有更好的方法来使用 Collection 方法创建“anchorfound”映射,或者香草 Java“foreach”结构是生成这种数据结构的最佳方法吗?

对于我的代码中的任何明显错误,我深表歉意。我的正式培训不是计算机科学,但我想更多地了解 Java 的函数式编程概念的实现。

Era*_*ran 5

我相信你需要的是一个 flatMap。

通过这种方式,您可以将外部映射的每个键转换为相应内部映射的键流,然后将它们展平为单个字符串流。

public class MyClass {
  private Map<String, Map<String, Short>> anchorLookup;
  ...
  public void CheckMissingAnchors(...){

    Map<String, Boolean> anchorfound = anchorLookup.keySet()
      .stream()
      .flatMap(s -> anchorlookup.get(s).keySet().stream())
      .collect(Collectors.toMap((s) -> s, (s) -> false);
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)


Stu*_*rks 5

伊兰的建议flatMap是一个很好的一个,+1。

这可以通过使用Map.values()而不是稍微简化Map.keySet(),因为映射的键除了检索值之外不用于任何其他目的。流式传输的结果Map.values()给出了一个Stream<Map<String,Short>>. 这里我们不关心内部映射的值,所以我们可以使用keySet()来提取键,给出一个Stream<Set<String>>. 现在我们只需将flatMap这些集合放入Stream<String>. 最后,我们像以前一样将结果发送到收集器中。

生成的代码如下所示:

public class MyClass {
    private Map<String, Map<String, Short>> anchorLookup;

    public void checkMissingAnchors() {
        Map<String, Boolean> anchorfound = anchorLookup.values().stream()
            .map(Map::keySet)
            .flatMap(Set::stream)
            .collect(Collectors.toMap(s -> s, s -> false));
    }
}
Run Code Online (Sandbox Code Playgroud)