For example, given a map like below:
{
"k1": {
"k2": {
"k3": {
"k4": "v"
}
}
}
}
and a field list ["k1","k2","k3"]
, I need to retrieve the part {"k4": "v"}
.
Below is my java7-style code:
// Ignore the map building code.
Map map1 = new HashMap();
Map map2 = new HashMap();
Map map3 = new HashMap();
Map map4 = new HashMap();
map4.put("k4", "v");
map3.put("k3", map4);
map2.put("k2", map3);
map1.put("k1", map2);
Map map = map1;
System.out.println(map); //=> {k1={k2={k3={k4=v}}}}
// Code to be transformed to java8 style
List<String> fields = Arrays.asList("k1", "k2", "k3");
for(String field: fields) {
map = (Map) map.get(field);
}
System.out.println(map); //=> {k4=v}
Then how to transform above code to java 8 stream style?
I don’t think that there is any benefit in converting this into a functional style; the loop is fine and precisely expresses what you are doing.
But for completeness, you can do it the following way:
map = (Map)fields.stream()
.<Function>map(key -> m -> ((Map)m).get(key))
.reduce(Function.identity(), Function::andThen).apply(map);
This converts each key to a function capable of doing a map lookup of that key, then composes them to a single function that is applied to you map
. Postponing the operation to that point is necessary as functions are not allowed to modify local variables.
It’s also possible to fuse the map
operation with the reduce
operation, which allows to omit the explicit type (<Function>
):
map = (Map)fields.parallelStream()
.reduce(Function.identity(), (f, key)->f.andThen(m->((Map)m).get(key)), Function::andThen)
.apply(map);
Maybe you recognize now, that this is a task for which a simple for
loop is better suited.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With