【问题标题】:How to convert csv to a map using Java 8 Stream如何使用 Java 8 Stream 将 csv 转换为地图
【发布时间】:2016-07-28 17:32:57
【问题描述】:

我正在尝试创建一个简单的解析工具,用于转换两列 CSV 文件并将其放入地图中。

public Map<String, String> getMapFromCSV(final String filePath) throws IOException {
    return Files.lines(Paths.get(filePath))
                .map(line -> line.split(","))
                .collect(Collectors.toMap(line -> line[0], line -> line[1]));
}

如您所见,我正在创建一个字符串流,用逗号分隔每一行并将其转换为字符串数组,最后将键映射到索引 0,将值映射到索引 1。

@Test
public void testGetMapFromCSV() throws IOException{
    actual = util.getMapFromCSV(filePath).get("AL");
    expected = "ALABAMA";

    assertEquals(expected, actual);
}

由于某种原因,当我运行此测试时,实际值为 null。我排除了无效的文件路径,因为它在另一个单元测试中工作正常,并且键值存在于 CSV 中。我已经盯着它看了几个小时,想也许这里有人可以指出我的错误。

另外,我对 Java 8 还很陌生,所以如果有人知道更好/更简洁的编写方式,我将不胜感激。

【问题讨论】:

  • 你在这里泄露了一个文件描述符。 Files.lines() 应该在 try-with-resources 语句中打开。
  • 文件中有空格吗?
  • null 可能暗示map.get(key) 在地图中找不到key。尝试打印util.getMapFromCSV(filePath) 返回的整个地图。
  • @fge 没有 collect() 关闭流?
  • 不,它没有。它消耗所有元素但不调用.close()。你必须自己做。 (顺便说一下,实现AutoCloseable的是BaseStream,而Stream扩展了BaseStream

标签: java csv lambda java-8 java-stream


【解决方案1】:

好的,我添加了lines.close() 并从 csv 中删除了所有空格,它可以工作了!奇怪,考虑到 csv 在我的其他方法中得到了很好的解析。这是它的样子:

public static Map<String, String> getMapFromCSV(final String filePath) throws IOException{

        Stream<String> lines = Files.lines(Paths.get(filePath));
        Map<String, String> resultMap = 
                lines.map(line -> line.split(","))
                     .collect(Collectors.toMap(line -> line[0], line -> line[1]));

        lines.close();

        return resultMap;
    }

【讨论】:

  • 感谢分享!您知道在删除重复项的同时使用流的方法吗?
【解决方案2】:

使用AutoCloseable 尝试资源

作为commented by fge,使用try-with-resources 使这更容易。

这是来自your Answer 的代码,但使用try-with-resources 自动关闭Stream,也就是AutoCloseable。并添加了一些空格字符来获得喘息空间。

public static Map<String, String> getMapFromCSV(final String filePath) throws IOException{

    try (
        Stream < String > lines = Files.lines( Paths.get( filePath ) );
    )
    {
        Map < String , String > resultMap = 
                lines.map( 
                         line -> line.split( "," ) 
                     )
                     .collect(
                         Collectors.toMap( line -> line[0] , line -> line[1] )
                     );
        return resultMap;
    }
    // The `Stream` named `lines` is automatically closed at this point by the try-with-resources.
}

当 try-with-resources 的 {…} 块结束时,try 中打开的所有资源都将自动关闭,其打开顺序与打开顺序相反。无论控制流在完成时优雅地离开块,还是由于异常或return(如您的代码中所示)而突然离开,这都是正确的。请参阅有关此问题的讨论,Try-with-resources and return statements in java

【讨论】:

    【解决方案3】:

    以一种更容易阅读的形式——使用mapping

    public static Map<String, String> getMapFromCSV(final String filePath) throws IOException {
      try(Stream<String> lines = Files.lines(Paths.get(filePath))) {
          return lines.collect(
            mapping(s -> s.split(","), toMap(k -> k[0], v -> v[1])));
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2017-06-16
      • 2014-07-18
      • 1970-01-01
      • 1970-01-01
      • 2019-12-06
      • 2020-03-07
      • 2018-05-03
      相关资源
      最近更新 更多