I have a CSV file, looking like this:
First, Surname, Age
Jim, Halpert, 35
Dwight, Schrute, 38
And I need to store it by Column (List of First names, list of surnames, list of ages). And I created a list of lists that would store this representation.
List<List<String>> myList = new ArrayList<List<String>>();
while ((row = csvReader.readLine()) != null)
{
String[] myRow = row.split(",");
for (int j=0; j<COLUMN_COUNT; j++)
{
myList.get(j).add(i,myRow[j]);
System.out.println(data.get(j).get(i));
}
i++;
}
My question is since I know what COLUMN_COUNT is, why doesn't this work? I am just trying to go through every line, and in every line, I separate the CSV to an array and then want to store this in a column-based list of lists.
The actual error I am getting is:
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
and the error happens on the line myList.get(j)...
Thanks
Edit
Some of you suggested working examples, which now I am using, so thank you very much for that, Now, I am thinking that I might use Java Streams. so it would take less code and be more optimized: However when I do:
List<List<String>> myList = Files.lines(Path.of(csvPath)) // Stream<String>
// .skip(1) // (optional) skip a header line
.map(line -> Arrays.stream(line.split("\\s*,\\s*")) // split by comma and trim whitespaces
.collect(Collectors.toList()) // get list of columns
) // Stream<List<String>>
.collect(Collectors.toList());
I only get something like this as a result:
[Jim, Halpert, 35]
[Dwigth, Schrute, 38]
But I actually need
[Jim, Dwight]
[Helpert, Schrute]
[35,38]
Any suggestions? Thanks!
You have created myList
but it is empty, it doesn't contains lists to handle values of each columns, you need to pre-fill it
// Add a list for each column
for (int j = 0; j < COLUMN_COUNT; j++) {
myList.add(new ArrayList<>());
}
Then you may add the date, and you don't need an i
to set the value in the sublist, just append it after the other values
while ((row = csvReader.readLine()) != null) {
String[] myRow = row.split(",");
for (int j = 0; j < COLUMN_COUNT; j++) {
myList.get(j).add(myRow[j]);
}
}
If the format of CSV file is simple (without double quoted strings, escaped commas, etc.), such file could be read in a simpler way using Stream API with new Files::lines
method providing a stream of Strings:
List<List<String>> data = Files.lines(Path.of(csvFileName)) // Stream<String>
// .skip(1) // (optional) skip a header line
.map(line -> Arrays.stream(line.split("\\s*,\\s*")) // split by comma and trim whitespaces
.collect(Collectors.toList()) // get list of columns
) // Stream<List<String>>
.collect(Collectors.toList());
Otherwise, appropriate library should be used to read CSV data like Apache Commons CSV
Update
In order to convert a stream of string lines/rows into columnar view List<List<String>>
, the algorithm is as follows:
flatMap
)collectingAndThen
to collect incoming map entries into a map, and convert the latter into List<List<String>>
:static List<List<String>> toColumnList(Stream<String> lines) {
return lines
.map(line -> line.split("\\s*,\\s*")) // Stream<String[]>
.flatMap(arr -> IntStream.range(0, arr.length)
.mapToObj(i -> Map.entry(i, arr[i])) // Stream<Integer, String>, i - column index
)
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(
Map.Entry::getKey, // group by column indexes
Collectors.mapping(
Map.Entry::getValue,
Collectors.toList()
)), // Map<Integer, List<String>>
map -> new ArrayList<>(map.values()) // convert map values to List<List<String>>
));
}
Test
System.out.println(toColumnList(
Stream.of("John, Doe, 38", "Dwight, Wright, 45", "Jim, Beam, 40")
));
Output
[[John, Dwight, Jim], [Doe, Wright, Beam], [38, 45, 40]]
you will ned something like this
int column_count = 3;
List<List<String>> myList = new ArrayList<List<String>>();
for (int i = 0; i < column_count; i++) {
myList.add(new ArrayList<String>());
}
while ((row = csvReader.readLine()) != null){
String[] split = row.split(",");
for (int i = 0; i < split.length; i++) {
myList.get(i).add(split[i]);
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.