Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java 8: Convert a map with string values to a list containg a different type

I have this Map:

Map<Integer, Set<String>> map = ...

And I have this class Foo:

class Foo {
    int id;
    String name;
}

I want to convert the map to List<Foo>. Is there a convenient manner in Java 8 to do this?

Currently, my way is:

List<Foo> list = new ArrayList<>((int) map.values().flatMap(e->e.stream()).count()));

for(Integer id : map.keySet()){
    for(String name : map.get(id)){
        Foo foo = new Foo(id,name);
        list.add(foo);  
    }
}

I feel it's too cumbersome.

like image 459
zhuguowei Avatar asked Feb 09 '23 11:02

zhuguowei


2 Answers

You can have the following:

List<Foo> list = map.entrySet()
                    .stream()
                    .flatMap(e -> e.getValue().stream().map(name -> new Foo(e.getKey(), name)))
                    .collect(toList());

For each entry of the map, we create a Stream of the value and map it to the corresponding Foo and then flatten it using flatMap.

like image 54
Tunaki Avatar answered May 01 '23 05:05

Tunaki


The main reason for your version being cumbersome is that you have decided to calculate the capacity of the ArrayList first. Since this calculation requires iterating over the entire map, there is unlikely to be any benefit in this. You definitely should not do such a thing unless you have proved using a proper benchmark that it is needed.

I can't see anything wrong with just using your original version but with the parameterless constructor for ArrayList instead. If you also get rid of the redundant local variable foo, it's actually fewer characters (and clearer to read) than the stream version.

like image 25
Paul Boddington Avatar answered May 01 '23 04:05

Paul Boddington