So my text file contains 5 fields, i would like to create a Map<Pair<String, String>,List<List<String>>>
from of it, where Pair is an instance of Apache's ImmutablePair
having 2 of the 5 fields as key, the value of that Map would be a List<List<String>>
where each List<String>
for the key, would contain the remaining 3 fields, so if the file would be like:
A,B,1,2,3
A,C,4,5,9
A,B,3,4,5
A,C,5,6,7
The result Map would be like:
K:(A,B)
V:((1,2,3),(3,4,5))
K:(A,C)
V:((4,5,9),(5,6,7))
I am trying to achieve this by making as much as possible use of lambdas and streams, here is my temporary code,, which works, but it returns as value the entire line:
private Map<Pair<String, String>, List<List<String>>> createMultimapFromFile() {
Map<Pair<String, String>, List<List<String>>> map = new BufferedReader(
new InputStreamReader(getClass().getResourceAsStream(MAPING_FILENAME)))
.lines()
.map(line -> Arrays.asList(line.split(COMMA)))
.filter(lineAsList -> lineAsList.size() == REQUIRED_FILE_LINE_LENGTH)
.collect(Collectors.groupingBy(filteredLine ->
ImmutablePair.of(filteredLine.get(1), filteredLine.get(2))));
return map;
}
This call to Collectors.groupingBy
makes use of this implmentation, which defaults to returning the map values as List<T>
but what i would like and i cannot find is returning a sublist, to save space in memory.
I was under the impression that this is the right method, as the description says...
"and then performing a reduction operation on the values associated with a given key using the specified downstream Collector."
Is just cant find a pre made Collector where i can specify the code to finalize the list.
Anyone has any tip?
Collectors#mapping
would do the work for you.
try(BufferedReader reader = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(MAPING_FILENAME), "utf-8"))) {
return reader.lines()
.map(line -> line.split(","))
.filter(lineAsList -> lineAsList.length == REQUIRED_FILE_LINE_LENGTH)
.map(data -> Pair.of(ImmutablePair.of(data[0], data[1]), Arrays.asList(data[2], data[3], data[4])))
.collect(Collectors.groupingBy(p -> p.getLeft(), Collectors.mapping(p -> p.getRight(), Collectors.toList())));
} catch (Exception e) {}
And Output would be like this,
{(A,C)=[[4, 5, 9], [5, 6, 7]], (A,B)=[[1, 2, 3], [3, 4, 5]]}
Pair
is tuple from apache commons-lang library. Using here just to hold values. You can use any other object for that purpose.
alternatively, can be written like this as well
.map(data -> Pair.of(ImmutablePair.of(data[0], data[1]), Arrays.asList(data[2], data[3], data[4])))
.collect(Collectors.groupingBy(p -> p.getLeft(), Collectors.mapping(p -> p.getRight(), Collectors.toList())));
//without pair
.collect(Collectors.groupingBy(data -> ImmutablePair.of(data[0], data[1]), Collectors.mapping(data -> Arrays.asList(data[2], data[3], data[4]), Collectors.toList())));