Reputation: 1658
There is class Person:
class Person {
private String id;
private String name;
private int age;
private int amount;
}
and I have created HashMap
of Person
using external file contains lines:
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]))));
}
}
}
It works fine for HashMap
.
How to do the same for ArrayList
?
I tried:
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 is underlined in red "a[0]" and says "Array type expected,found : lambda parameter")
Upvotes: 4
Views: 1080
Reputation: 11042
I would recommend adding a `static method (or according constructor) to your person class which parses the CSV string:
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]));
}
To read the lines you can alternatively use Files.lines()
. Using all that you can use this to create you List<Person>
:
try (Stream<String> lines = Files.lines(Paths.get("./person.txt"))) {
List<Person> persons = lines
.map(Person::fromCSV)
.collect(Collectors.toList());
}
Upvotes: 1
Reputation: 187
What you did is on correct lines, only thing missing is that you create the Person object in collect, instead you could create it inside the map method itself and return that and use the collect method with Collectors.toList() method. Below code snippet will give a good idea of what I am trying to convey:
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());
This way you use the map method only once, and return the object that is needed which the collect method consolidates into a List. If you want it to be an ArrayList you can use Collections framework to cast List to ArrayList, but I think List should be fine for your operations.
Upvotes: 0
Reputation: 847
Why to map twice? You can directly do this,
.map(s -> {
String[] parts = s.split(",");
return new Person(parts[0],parts[1],Integer.valueOf(parts[2]),Integer.valueOf(parts[3]));
}).collect(Collectors.toList());
Upvotes: 1
Reputation: 31868
You need to map
it to the Person
object before trying to collect
it:
.map(s -> s.split(","))
.map(a -> new Person(a[0],a[1],Integer.valueOf(a[2]),Integer.valueOf(a[3])) //here
.collect(Collectors.toList())
Upvotes: 2
Reputation: 393771
You should use map
in order to map each array to a corresponding Person
instance:
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());
BTW, Collectors.toList()
returns a List
, not an ArrayList
(even if the default implementation does return ArrayList
, you can't count on that).
Upvotes: 11