Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java 8 stream convert complex map


I have a map with such structure: Map<R, Map<S, Map<D, K>>> and I need to convert it to Map<R, Map<D, Map<S, K>>> any idea how to implement it with streams?
In my case it looks like: Map<Long, Map<String, Map<Long, Double>>>
And the data:

{1->{"m"->{2->3.0},{3->1.0},{4->2.0}}}
{1->{"n"->{2->1.0},{3->2.2},{5->3.2}}}


Thanks.

like image 932
Behemoth Avatar asked Dec 24 '15 12:12

Behemoth


1 Answers

First off, it appears that the outer map level is not involved in the transformation, so let's forget about it for the time being. You have Map<S,Map<D,K>> and you want to turn it into Map<D,Map<S,K>>. You could try the following:

Map<S,Map<D,K>> src = ...;
Map<D,Map<S,K>> dest = src.entrySet().stream() // Stream<Map.Entry<S,Map<D,K>>>
    .flatMap(eO -> {
        final S curS = eO.getKey();
        return eO.getValue().entrySet().stream() // Stream<Map.Entry<D,K>>
            .map(eI -> new Object[] { curS, eI.getKey(), eI.getValue() });
            // Stream<Object[]{S,D,K}> for this S
    }) // Stream<Object[]{S,D,K}> for all S
    .collect(Collectors.groupingBy(
            arr -> (D)arr[1], // What to group by in the outer level
            Collectors.toMap( // What to do with the inner level values for each D
                arr -> (S)arr[0], // Keys for the inner map
                arr -> (K)arr[2]  // Values for the inner map
    )));

Of course, the code might seem a bit awkward due to the use of casts, but it avoids the need for a type-safe 3-tuple class. Take a deep look at the code because I'm away from any Java compiler, but I think it ought to do what you want it to do.

like image 75
Javier Martín Avatar answered Nov 10 '22 08:11

Javier Martín