Issue
I have a List of objects A, where the object A has this form:
Class A {
private String a1;
private String a2;
private String a3;
private String a4;
private String a5;
private String a6;
}
I need to group this List first by a1 and then by a3, resulting in this way:
Map<B, Map<C, List<D>>>
, where the object B has this form
Class B {
private String a1;
private String a2;
}
and where the object C has this form
Class C {
private String a3;
private String a4;
}
and where the object D has this form
Class D {
private String a5;
private String a6;
}
Is this possibile with streams in Java 11? Any other ways to achieve this goal are welcome, thanks very much!
Solution
Suppose you have these lombok annotations on your classes (It's fine if you don't have lombok - you can just add these boilerplate to your classes if you don't have them already):
@Getter
class A {
private String a1;
private String a2;
private String a3;
private String a4;
private String a5;
private String a6;
}
@AllArgsConstructor
@EqualsAndHashCode(exclude = "a2")
class B {
private String a1;
private String a2;
}
@AllArgsConstructor
@EqualsAndHashCode(exclude = "a4")
class C {
private String a3;
private String a4;
}
@AllArgsConstructor
class D {
private String a5;
private String a6;
}
Note that it is important that B
and C
's equals
and hashCode
only depend on a1
and a3
respectively.
Then given List<A> aList
, you can nest the groupingBy
collectors like this, and at the very end, map each thing to a D
.
var map = aList.stream().collect(
Collectors.groupingBy(
x -> new B(x.getA1(), x.getA2()),
Collectors.groupingBy(
x -> new C(x.getA3(), x.getA4()),
Collectors.mapping(
x -> new D(x.getA5(), x.getA6()),
Collectors.toList()
)
)
)
);
and map
will be a Map<B, Map<C, List<D>>>
.
Answered By - Sweeper
Answer Checked By - Senaida (JavaFixing Volunteer)