Given,
class Foo {
private Long id;
private String name;
private String category;
private List<String> categories;
// getters & setters
}
I have a list of objects.
final Foo f1 = new Foo(1L, "a", "c1");
final Foo f2 = new Foo(1L, "a", "c2");
final Foo f3 = new Foo(2L, "a", "c1");
final List<Foo> li = List.of(f1, f2, f3);
which looks like
{[Foo [id=1, name=a, category=c1, categories=null], Foo [id=1, name=a, category=c2, categories=null]], [Foo [id=2, name=a, category=c1, categories=null]]}
I want to transform this to
[Foo [id=1, name=a, category=null, categories=[c1, c2]], Foo [id=2, name=a, category=null, categories=[c1]]]
i.e. collate the individual category
into a list of categories
.
This is the current code that achieves what I want.
public static void main(final String[] args) {
final Foo f1 = new Foo(1L, "a", "c1");
final Foo f2 = new Foo(1L, "a", "c2");
final Foo f3 = new Foo(2L, "a", "c1");
final List<Foo> li = List.of(f1, f2, f3);
li.forEach(e -> System.out.println(e));
final Map<Long, List<Foo>> collect = li.stream().collect(Collectors.groupingBy(Foo::getId));
System.out.println(collect);
final List<Foo> grouped = new ArrayList<>();
collect.forEach((k, v) -> {
System.out
.println("key=" + k + "val=" + v.stream().map(e1 -> e1.getCategory()).collect(Collectors.toList()));
final Foo foo = collect.get(k).get(0);
foo.setCategories(v.stream().map(e1 -> e1.getCategory()).collect(Collectors.toList()));
foo.setCategory(null);
grouped.add(foo);
});
System.out.println(grouped);
}
Is there any way to do this using streams & lambdas alone without having to break into multiple steps? The goal is to make this code more elegant, readable, and convey the intention to the reader.
This question is similar in nature to Group by and sum objects like in SQL with Java lambdas? but didn't help me since there an aggregation is done whereas here it's not an aggregation.