Anuj Kumar Soni
Anuj Kumar Soni

Reputation: 192

how to sort nested lists in java

I have a json like below :

{ 
  "Student": [
    {  
      "name":"5",
      "Roll No":12345,
      "Subjects":[  
        {  
           "subjectCode":"Mat"
        },
        {  
           "subjectCode":"Sci"
        }
      ]
    } 
  ]
}

I want to sort list of subjects within each student and then sorting student objects with roll no.Can it be done with java8 in single line.

I am using below code :

list.forEach(studentObj -> {
    studentObj.getSubjects()
      .sort(Comparator.nullsLast(Comparator.comparing(Subject:: getSubjectCode)));
  });

then sorting the outside object

  list.sort(Comparator.nullsLast(Comparator.comparing(Student:: getRollNo)));

Upvotes: 8

Views: 10481

Answers (4)

Hadi
Hadi

Reputation: 17289

Try this one

List<Student> result = new ArrayList<>();
studentList.stream()
           .sorted(Comparator.comparingInt(Student::getRollNo))
           .map(student -> {
                student.getSubjects().sort(Comparator.nullsLast(Comparator.comparing(Subjects::getSubjectCode)));
                return student;
            }).collect(Collectors.toList());

Upvotes: -1

Bentaye
Bentaye

Reputation: 9756

If you were to implement the Comparable interface with your 2 classes Student and Subject you could make it really nice and short because you can use the Comparator.naturalOrder() static factory method

Also it allows you to change the way you want to define how Subjects or Students get ordered by simply changing their compareTo method

Student

class Student implements Comparable<Student> {
    String name;
    int rollNo;
    List<Subject> subjects = new ArrayList<>();

    // GETTERS/SETTERS

    @Override
    public int compareTo(Student student) {
        return Integer.compare(this.getRollNo(), student.getRollNo());
    }

}

Subject

class Subject implements Comparable<Subject> {
    String subjectCode;

    // GETTERS/SETTERS

    @Override
    public int compareTo(Subject subject) {
        return this.getSubjectCode().compareTo(subject.getSubjectCode());
    }

}

And then

// static import to make code lighter
import static java.util.Comparator.*;

// sort Students list, then sort Subjects list in each Student
list.sort(nullsLast(naturalOrder()));
list.forEach(s -> { if (s != null) {
   s.getSubjects().sort(nullsLast(naturalOrder())); 
}});

One liner version if you really need it

List<Student> sortedList = list.stream()
    .map(s -> {
        if (s != null) {
            s.getSubjects().sort(nullsLast(naturalOrder()));
        }
        return s;
    }).sorted(nullsLast(naturalOrder()))
    .collect(Collectors.toList());

Upvotes: 5

Michał Marcinkowski
Michał Marcinkowski

Reputation: 620

After parsing it to object you could write something like below:

List<Student> sorted = students.stream()
            .map(f -> new Student(f.getId(), f.getSubjects().stream().sorted(Comparator.comparing(Subject::getSubjectCode)).collect(Collectors.toList())))
            .sorted(Comparator.comparing(Student::getRollNo))
            .collect(Collectors.toList())

Upvotes: 2

Joe
Joe

Reputation: 1342

Here are a few one liner examples that should get you started, using java streams.

List<String> sorted = new ArrayList<>(Arrays.asList("Input1", "Input2", "Etc")).stream().sorted((a, b) -> a.compareTo(b));


List<String> sorted = json.stream().sorted((a, b) -> a.compareTo(b));


List<String> sorted = json.stream().sorted();

Here is how to sort all lists inside of a list, so you can refactor now to make it a one liner

void method() {
    sort(list);
}

void sort(List list) {
    if (list.size() == 0)
        return;

    list.stream().sorted();
    for (Object o : list)
        if (o instanceof List)
            sorted((List) o);
}

Here are some references to java streams:

API Docs:

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

Examples:

https://stackify.com/streams-guide-java-8/

https://www.geeksforgeeks.org/stream-in-java/

Upvotes: 0

Related Questions