下面有一个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功能编写上述方法?
答案 0 :(得分:3)
您可以使用Files.lines(path)
在文件的行上检索Stream(您可以使用Paths.get
获得Path
)。使用skip(1)
跳过标题行,然后每行分为","
。
最后,Stream元素按键的第一个元素(删除了引号)进行分组,并将值映射到键的第二个元素的Double
值并收集到{{1} }。组操作使用groupingBy(classifier, downstream)
收集器完成:分类器是一种方法,它将密钥返回到分组依据,下游收集器收集分组到同一密钥的所有流元素;在这种情况下,对于具有相同键的值,我们希望将Stream元素映射到List
值(mapping
)并将这些Double
收集到Double
中( toList()
)。
你的设计中的问题是你的方法采用List
作为参数,并在最好让方法返回它时改变它。
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())
));
}
}
而不是让它无所事事。如果要在方法本身中处理该异常,仍可以添加catch部分。
答案 1 :(得分:2)
您可以像这样使用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())));
主要技巧是跳过第一个条目。
答案 2 :(得分:-1)
您可以使用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){}
在第一次转换之后,您可以重新考虑“解析”代码的结构,以便使用“filter”,“map”等操作将其置于更具功能性的结构中。