繁体   English   中英

Java 8 I / O流应用程序

[英]java 8 i/o stream application

我下面有一个CSV文件,我写了下面的方法来解析文件。

"PRODUCT_NAME","PRODUCT_CATEGORY","SALES_PRICE"
"Hair Gel","Beauty",6.99 
"Scotch tape","Office Supply",2.99
"Office Chair","Office Supply",134.99

我的代码:

public static void ReadFile(String path, Map<String, List<Double>> db){
    try(BufferedReader br = new BufferedReader(new FileReader(path))){
        String line;
        if((line = br.readLine()) != null){
            //this line is the heading..and needed to be skipped
        }
        while ((line = br.readLine()) != null) {
            String[] keys = line.split(",");
            keys[1] = keys[1].replace("\"", "");
            if(db.containsKey(keys[1])){
                List<Double> list = db.get(keys[1]);
                list.add(Double.valueOf(keys[2]));
                db.put(keys[1], list);
            }
            else{
                List<Double> list = new ArrayList<>();
                list.add(Double.valueOf(keys[2]));
                db.put(keys[1],list);
            }
        }

    }catch(IOException e){}
}

它在解析文件时工作正常,但我的主要问题是如何利用java8流和lambda功能编写上述方法?

您可以使用Files.lines(path)在文件的各行上检索Stream(也可以通过Paths.get获得Path )。 skip(1)跳过标题行,然后将每一行围绕在","周围。

最后,将Stream元素按键的第一个元素分组(除去引号),并将值映射到键的第二个元素的Double值,并将其收集到List 分组操作是通过groupingBy(classifier, downstream)收集器完成的:分类器是一种将键返回给group by的方法,下游收集器收集分组到同一键的所有Stream元素; 在这种情况下,对于具有相同键的值,我们想将Stream元素mappingDouble值( mapping ),并将这些Double收集到一个ListtoList() )。

设计中的问题是您的方法将Map<String, List<Double>> db作为参数,并在最好让该方法返回它时对其进行突变。

public static Map<String, List<Double>> readFile(String path) throws IOException {
    try (Stream<String> stream = Files.lines(Paths.get(path))) {
        return stream.skip(1)
                  .map(l -> l.split(","))
                  .collect(Collectors.groupingBy(
                    keys -> keys[1].replace("\"", ""),
                    Collectors.mapping(keys -> Double.valueOf(keys[2]), Collectors.toList())
                  ));
    }
}

请注意,我还修改了您的代码,以使其抛出IOException而不是捕获它而不执行任何操作。 如果要在方法本身中处理该异常,仍然可以添加catch部分。

您可以像这样使用Stream API

Map<String, List<Double>> rows = Files.lines(Paths.get("file"))
        .skip(1)
        .map(s -> s.split("\"?,\"?"))
        .collect(Collectors.groupingBy(s -> s[1], 
                 Collectors.mapping(s -> Double.parseDouble(s[2]), Collectors.toList())));

主要技巧是跳过第一个条目。

您可以使用BufferedReader.lines ,它返回带有文件行的Stream<String> 首先,您可以用它替换I / O代码:

try(Stream<String> fileLines = Files.lines(Paths.get(path))){
    fileLines.forEach(line -> {
        // Your code inside the "while" loop would go here
    });
}catch(IOException e){}

在完成第一个转换之后,您可以重新考虑“解析”代码的结构,以便使用诸如“过滤器”,“映射”之类的操作将其放入功能更强大的结构中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM