I have a list of students studentList
and i want to seperate them based on their class and section into a Map<CustomKey, List<Student>>
.
class Student {
public String Name;
public String Class;
public String Section;
}
I have a custom Key Class
class CustomKey {
public String Class;
public String Section;
}
I'm trying to group them using this, but we can clearly see what I'm doing wrong.
studentList.stream().collect(Collectors.groupingBy(x -> new CustomKey(x.Class, x.Section)));
The expression inside groupingBy is incorrect. Extending the Student Class is not allowed :(
I want to create this output
{
{"ClassA", "SectionA"}: [{name, class, section}, {name, class, section}],
{"ClassA", "SectionB"}: [{name, class, section}],
{"ClassB", "SectionA"}: [{name, class, section}, {name, class, section}],
}
My knowledge is very limited on JAVA. And any help/pointers are welcomed. Also, Apologies for the messed-up cases.
CodePudding user response:
i used your code exactly like below and it works for me
public void testCustomGroupBy(){
List<Student> studentList = new ArrayList<>();
studentList.add(new Student("name_1","class_1","section_1"));
studentList.add(new Student("name_2","class_1","section_1"));
studentList.add(new Student("name_3","class_2","section_1"));
studentList.add(new Student("name_4","class_2","section_2"));
studentList.add(new Student("name_5","class_2","section_2"));
Map<CustomKey, List<Student>> studentsBySection = studentList.stream().collect(Collectors.groupingBy(x -> new CustomKey(x.getClassName(), x.getSection())));
studentsBySection.entrySet().forEach(System.out::print);
}
create your pojo like below
class Student {
public String name;
public String className;
public String section;
// getters and setters
public Student(String name, String className, String section) {
this.name = name;
this.className = className;
this.section = section;
}
}
class CustomKey {
public String className;
public String section;
// getters and setters
public CustomKey(String className, String section) {
this.className = className;
this.section = section;
}
}
output
CustomKey(className=class_2, section=section_2)=[Student(name=name_4, className=class_2, section=section_2), Student(name=name_5, className=class_2, section=section_2)]
CustomKey(className=class_2, section=section_1)=[Student(name=name_3, className=class_2, section=section_1)]
CustomKey(className=class_1, section=section_1)=[Student(name=name_1, className=class_1, section=section_1), Student(name=name_2, className=class_1, section=section_1)]
CodePudding user response:
Well, CustomKey
is matched by its equals
method, which you don't have overridden. If you implement equals
(and also hashCode
) properly, then it'll work.
What's even better, is to create a record for CustomKey
:
public record CustomKey(String className, String section) { }
This'll let the compiler auto-generate its equals
and hashCode
implementations for free, as well as getters, the canonical constructor and the toString
method. The above record definition is equivalent to this:
public final class CustomKey {
private final String className;
private final String section;
public CustomKey(String className, String section) {
this.className = className;
this.section = section;
}
public String className() {
return className;
}
public String section() {
return section;
}
@Override
public boolean equals(Object o) {
return getClass() == o.getClass()
&& Objects.equals(className, o.className)
&& Objects.equals(section, o.section);
}
@Override
public int hashCode() {
return Objects.hash(className, section);
}
@Override
public String toString() {
return "CustomKey[className=" className ", section=" section "]";
}