Suppose I have a multi-map like this:
MiddleName -> null
EmailAddress -> Toni@mymail.com, Mary@hermail.com, Paul@hismail.com
FirstName -> Toni, Mary, Paul
LastName -> Barry, null ,White
Id -> null
Note how each "values" entry can be entirely null or contain the same number of values as the one with more entries (which I don't know which is) even if some are null.
I want it to "transpose" it to a list of maps like this:
MiddleName -> null
EmailAddress -> Toni@mymail.com
FirstName -> Toni
LastName -> Barry
Id -> null
MiddleName -> null
EmailAddress -> Mary@hermail
FirstName -> John
LastName -> null
Id -> null
MiddleName -> null
EmailAddress -> Paul@hismail.com
FirstName -> Paul
LastName -> White
Id -> null
I'm trying to do this with java8 streams, but can do it in the "old" style as well.
Searching stackoverflow I found a similar question [1] and a few more also related [2,3,4] that gave me some ideas but were not fully adaptable.
Now, I did implement my own solution that works as I want, but frankly this is probably the most ugly code I wrote in years...
List result = (...)
map.forEach(h -> {
MultiValueMap<String, String> m = new LinkedMultiValueMap();
h.entrySet().stream().forEach(e -> {
String[] ss = e.getValue() == null ? null : e.getValue().toString().split(",");
if (ss != null) {
Arrays.asList(ss).stream().forEach(s -> m.add(e.getKey(), s));
}
});
if (m.size() > 0) {
int x = m.values().stream().max((o1, o2) -> o1.size() - o2.size()).get().size();
for (int i = 0; i < x; i++) {
Map<String, String> n = (Map) h.clone();
Iterator<Map.Entry<String, String>> it = n.entrySet().iterator();
while( it.hasNext()){
Map.Entry<String, String> e = it.next();
List<String> ss = m.get(e.getKey());
if(ss!=null) {
e.setValue(ss.get(i));
}
}
result.add(n);
}
}
});
The first pass is just to split the string into a array since originally it's a comma separated string. Then I find the max number of elements in any value, I loop all the values in the entries for that number of times and create the a map for each value with the results. To be frank I wrote this code last Friday and I can't already read it properly...
So, this was at first a simple thing to do and I ended up with this mess, is there a better way to do it?
Thanks in advance.
[1] Java8 streams : Transpose map with values as list
[2] reversing keys/values - create new instance of HashMap
[3] "Transpose" a hashmap for key->value to value->key?
[4] Java invert map