Java Stream API 收集方法

问题描述 投票:0回答:5

有班人:

class Person {
    private String id;
    private String name;
    private int age;
    private int amount;
}

我已经使用外部文件创建了

HashMap
Person
包含行:

001,aaa,23,1200
002,bbb,24,1300
003,ccc,25,1400
004,ddd,26,1500

Mainclass.java

public class Mainclass {
public static void main(String[] args) throws IOException {
    List<Person> al = new ArrayList<>();
    Map<String,Person> hm = new HashMap<>();
    try (BufferedReader br = new BufferedReader(new FileReader("./person.txt"))) {
        hm = br.lines().map(s -> s.split(","))
                .collect(Collectors.toMap(a -> a[0], a-> new Person(a[0],a[1],Integer.valueOf(a[2]),Integer.valueOf(a[3]))));
    }
}

}

它适用于

HashMap

如何对

ArrayList
做同样的事情?

我尝试过:

    al = br.lines().map(s -> s.split(","))
                    .collect(Collectors.toList(a -> new Person(a[0],a[1],Integer.valueOf(a[2]),Integer.valueOf(a[3]))));

(IntelijIdea 用红色下划线“a[0]”表示“预期数组类型,找到:lambda 参数”)

java java-stream
5个回答
11
投票

您应该使用

map
来将每个数组映射到相应的
Person
实例:

al = br.lines().map(s -> s.split(","))
               .map (a -> new Person(a[0],a[1],Integer.valueOf(a[2]),Integer.valueOf(a[3])))
               .collect(Collectors.toList());

顺便说一句,

Collectors.toList()
返回一个
List
,而不是
ArrayList
(即使默认实现确实返回
ArrayList
,你也不能指望它)。


2
投票

在尝试

map
之前,您需要将其
Person
collect
对象:

.map(s -> s.split(","))
.map(a -> new Person(a[0],a[1],Integer.valueOf(a[2]),Integer.valueOf(a[3])) //here
.collect(Collectors.toList())

1
投票

为什么要映射两次?你可以直接这样做,

.map(s -> {
            String[] parts = s.split(",");
            return new Person(parts[0],parts[1],Integer.valueOf(parts[2]),Integer.valueOf(parts[3]));
        }).collect(Collectors.toList());

1
投票

我建议在您的 person 类中添加一个`静态方法(或根据构造函数)来解析 CSV 字符串:

public static Person fromCSV(String csv) {
    String[] parts = csv.split(",");
    if (parts.length != 4) {
        throw new IllegalArgumentException("csv has not 4 parts");
    }
    return new Person(parts[0], parts[1], Integer.parseInt(parts[2]), Integer.parseInt(parts[3]));
}

要阅读这些行,您也可以使用

Files.lines()
。使用所有你可以用它来创造你的东西
List<Person>
:

try (Stream<String> lines = Files.lines(Paths.get("./person.txt"))) {
    List<Person> persons = lines
            .map(Person::fromCSV)
            .collect(Collectors.toList());
}

0
投票

您所做的是正确的,唯一缺少的是您在collect中创建了Person对象,相反您可以在map方法本身内创建它并返回它,并将collect方法与Collectors.toList()方法一起使用。下面的代码片段可以很好地了解我想要传达的内容:

al= br.lines()
      .map(s -> {
                    String[] subStrings = s.split(",");
                    return new Person(subStrings[0], subStrings[1], Integer.valueOf(subStrings[2]), Integer.valueOf(subStrings[3]));
                })
      .collect(Collectors.toList());

这样你只使用一次map方法,并返回所需的对象,collect方法将其合并到一个List中。如果你希望它是一个 ArrayList,你可以使用 Collections 框架将 List 转换为 ArrayList,但我认为 List 应该适合你的操作。

© www.soinside.com 2019 - 2024. All rights reserved.