From List<Foo> to Map<String, List<Foo>>: looking for a better implementation
Asked Answered
D

2

7

Let me show you my code:

Class Foo

public class Foo {

    String code;
    String value;

    public Foo(String code, String value) {
        super();
        this.code = code;
        this.value = value;
    }
    // getters/setters
}

Main method (focus on getFooMultiMapCode() method):

public class FooMain {

public static void main(String[] args) {
    Foo foo1 = new Foo("100","foo1");
    Foo foo2 = new Foo("200","foo2");
    Foo foo3 = new Foo("300","foo3");
    Foo foo4 = new Foo("100","foo4");
    Foo foo5 = new Foo("100","foo5");
    Foo foo6 = new Foo("200","foo6");
    List<Foo> foos = Arrays.asList(foo1,foo2,foo3,foo4,foo5,foo6);  
    Map<String,List<Foo>> fooCodeMap = getFooMultiMapCode(foos);
    System.out.println(fooCodeMap);
}

private static Map<String, List<Foo>> getFooMultiMapCode(List<Foo> foos) {
    Map<String, List<Foo>> fooMultiMapCode = new HashMap<String, List<Foo>>();
    for(Foo foo:foos){
        List<Foo> list = fooMultiMapCode.get(foo.getCode());
        if(list==null){
            list = new ArrayList<Foo>();
            list.add(foo);
            fooMultiMapCode.put(foo.getCode(), list);
        }
        else {
            list.add(foo);
        }
    }
    return fooMultiMapCode;
}
}

Main prints correctly this string:

{100=[foo1, foo4, foo5], 200=[foo2, foo6], 300=[foo3]}

I would like to rewrite getFooMultiMapCode method in a more succint way using for example java8 or also libraries such lambdaj, guava, etc but I don't want to change method signature.

Diorama answered 5/11, 2016 at 13:19 Comment(1)
The non-stream variant: for(Foo foo:foos) fooMultiMapCode.computeIfAbsent(foo.getCode(), x -> new ArrayList<>()).add(foo);Baccate
A
11

The solution with Java 8 and groupingBy(classifier, downstream):

return foos.stream().collect(Collectors.groupingBy(Foo::getCode, Collectors.toList()));

Or simply with groupingBy(classifier) as @Boris the Spider noticed:

return foos.stream().collect(Collectors.groupingBy(Foo::getCode));
Adobe answered 5/11, 2016 at 13:22 Comment(1)
Java 8 is definitely marginally more succinct than previous versions...Sanfred
M
1

Expanding a bit on @Holgers comment: Non-stream version if you prefer loops - still java8, though:

private static Map<String, List<Foo>> getFooMultiMapCode(List<Foo> foos) {
    Map<String, List<Foo>> fooMultiMapCode = new HashMap<String, List<Foo>>();
    for(Foo foo : foos){
        fooMultiMapCode.computeIfAbsent(foo.getCode(), x -> new ArrayList<>()).add(foo);
    }
    return fooMultiMapCode;
}

or even

private static Map<String, List<Foo>> getFooMultiMapCode(List<Foo> foos) {
    Map<String, List<Foo>> fooMultiMapCode = new HashMap<String, List<Foo>>();
    foos.forEach(foo -> fooMultiMapCode.computeIfAbsent(foo.getCode(), x -> new ArrayList<>()).add(foo));
    return fooMultiMapCode;
}

I still prefer the stream version, though.

Manet answered 7/11, 2016 at 14:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.