I have a list of string arrays List<String[]> which looks like this:
List<String[]> dataLines = List.of(
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "84M", "-101.87", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "120M", "-102.48", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "60M", "-103.75", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "120M", "-10.8", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "60M", "-110.39", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4055", "120M", "-10.8", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "CZK", "12670012.4055", "60M", "-103.75", "0"},
new String[]{"2002", "BRBTSS", "BRSTNCNTF212", "BRL", "12670012.4066", "20M", "-10.8", "0"}
);
I want to create a new list of arrays List<String[]> newDataLine by grouping arrays where the 0th, 1st, 3rd, and 5th elements are same and add up their 6th elements.
Expected Output:
["2002","BRBTSS","BRSTNCNTF212","BRL","12670012.4055","84M","-101.87","0"],
["2002","BRBTSS","BRSTNCNTF212","BRL","12670012.4055","120M","-124.08000000000001","0"],
["2002","BRBTSS","BRSTNCNTF212","BRL","12670012.4055","60M","-214.14","0"],
["2002","BRBTSS","BRSTNCNTF212","CZK","12670012.4055","60M","-103.75","0"],
["2002","BRBTSS","BRSTNCNTF212","BRL","12670012.4066","20M","-10.8","0"]
I've tried the following:
Map<String, Map<String, Map<String, Map<String, Double>>>> map =
dataLines.stream()
.collect(Collectors.groupingBy(
s -> s[0],
Collectors.groupingBy(s -> s[1],
Collectors.groupingBy(s -> s[3],
Collectors.groupingBy(s -> s[5],
Collectors.summingDouble(s -> Double.valueOf(s[6])))))
));
Which gives me the following output:
{2002={BRBTSS={BRL={84M=-101.87, 60M=-214.14, 120M=-124.08000000000001}}}}
How can group the data in a way described above?
To group these arrays in the required way and merge their data, you can use a
HashMap, non-nested one. Nested maps, like the one in your code, are cumbersome and difficult to deal with.For that, we need an object which would serve as a Key. I'll use a Java 16
record, but it can be implemented aclassas well.If we translate it into a
classhere's how it would look like:Note:
List<String[]>- is not the most convenient type to dial with, and it's better to avoid mixing arrays and Collections.These Arrays should be custom Objects, to begin with, because you're expecting them to contain a particular number of elements and each to have a certain shape. If you organize them into a class, your data would have a structure, each element would become a property with an appropriate data type, instead of being a nameless String.
It's highly advisable to use
BigDecimalinstead ofDoublefor floating-point calculations when don't want to lose precision (e.g.). Although CollectorsummingDouble()is implemented to mitigate inaccuracies,doubleis not a good choice for calculating prices, tax rates, etc.And here how the stream would look like:
Output: