2

I want to convert a Map<String, List<MyObject>> to List<Map<String, MyObject>>

{<key1,[myObject1, myObject2]>, <key2,[myObject3, myObject4]>} will be converted to [{<key1,myObject1>, <key2,myObject3>}, {<key1,myObject2>, <key2, myObject4>}]

where myObject1 and myObject3 have a same unique id and so do myObject2 and myObject4.

my implementation is below but is there a more optimal way of doing this.

private List<Map<String, MyObject>> getObjectMapList( Map<String, List<MyObject>> objectMap)

{
  List<Map<String, MyObject>> objectMapList = new ArrayList<Map<String,MyObject>>();

 for(MyObject myObject : objectMap.get("key1")) {// there will be default key1 whose value is known

        Map<String, MyObject> newMap= new HashMap<String, MyObject>();
        for (String key : objectMap.keySet()) {
            newMap.put(key, objectMap.get(key).stream()
                    .filter(thisObject -> thisObject.getId().equals(myObject.getId()))
                    .collect(Collectors.toList()).get(0));
        }
        objectMapList.add(newMap);
    }
    return objectMapList;

}
2
  • Where does the language variable come from? Commented Mar 5, 2017 at 17:18
  • was some typo. edited it Commented Mar 6, 2017 at 6:29

2 Answers 2

1

Here's a 1-liner without any curly brackets:

private List<Map<String, MyObject>> getObjectMapList( Map<String, List<MyObject>> objectMap) {
    return map.entrySet().stream()
      .map(e -> e.getValue().stream()
      .map(o -> Collections.singletonMap(e.getKey(), o))
      .collect(Collections.toList())
    .flatMap(List::stream)
    .collect(Collections.toList());
}

The main "trick" here is the use of Collections.singletonMap() to allow a blockless in-line create-and-populate of a map.


Disclaimer: Code may not compile or work as it was thumbed in on my phone (but there's a reasonable chance it will work)

Sign up to request clarification or add additional context in comments.

2 Comments

Looks nice, I will keep the singletonMap in mind. But does this still group the pairs by MyObject.getId()? Or does each map in the result list only contain one mapping?
@MalteHartwig only one mapping
0

This stream should return you the desired result. With my old Eclipse version, I had some trouble with types. You might have to break it up into single steps, or add some types in the lambdas, but I wanted to keep it short.

Map<String, List<MyObject>> objectMap = new HashMap<>();

objectMap.keySet()
         .stream()
         .flatMap(key -> objectMap.get(key)
                                  .stream()
                                  .map(obj -> new AbstractMap.SimpleEntry<>(key, obj)))
         .collect(groupingBy(pair -> pair.getValue().getId()))
         .values()
         .stream()
         .map(listOfSameIds -> listOfSameIds.stream()
                                            .collect(toMap(SimpleEntry::getKey, SimpleEntry::getValue)))
         .collect(toList());

What I do is:

  1. Pair all the objects in all your input's values with their keys and put them in one long list (flatMap(key -> streamOfKeyObjectPairs)).
  2. Separate those pairs by the IDs of the objects (collect(groupingBy)).
  3. Take each of those groups and convert the lists of pairs into maps (map(list -> toMap))
  4. Put all those maps into a list

2 Comments

I was not able to get it work. groupingBy(pair -> pair.getValue().getId()) complains about unknown object event if split is into different operations
Did you add the import for the groupingBy method? Write Collectors.groupingBy to check whether the import is missing. Otherwise, you could try to explicitly type the pair parameter by replacing pair -> pair.getValue().getId() by (SimpleEntry<String, MyObject> pair) -> pair.getValue().getId(). If that still does not work, you could try assigning the lambda to a Function variable: Function<SimpleEntry<String, MyObject>, ID_TYPE> toID = pair -> pair.getValue().getId().

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.