8

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)));
10
  • 2
    Can it be done with java8 in single line? Yes probably, give it a try. Commented Jan 9, 2019 at 9:34
  • 15
    Technically every program can be written in single line. Commented Jan 9, 2019 at 9:35
  • Did you manage to map the JSON to an Object? Commented Jan 9, 2019 at 9:37
  • @Stultuske i have writtern the code above Commented Jan 9, 2019 at 9:41
  • 1
    @AnujKumarSoni we downvoted because your question was not clear and was showing no effort. Note that we all upvoted once you added your code. Commented Jan 9, 2019 at 9:48

4 Answers 4

5

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());
Sign up to request clarification or add additional context in comments.

2 Comments

I liked this approach as it has a flavor of core concept alongwith java8 functionality
@AnujKumarSoni Always consider implementing Comparable when you need your objects to be sorted.
2

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())

3 Comments

This is just an idea of dealing with such problems, not production ready solution.
Nice idea. The only problem with the solution is that mapping would now require a constructor while preserving all attributes of the same object. Maybe a method designed for sorting could have been better. Just that it won't fit again into a on-line kind of requirement.
@nullpointer yes, but during collection pipeline, we should not mute object but let them be unmutable because of the thread safety of solution. I have preassumed that students could be a parallel stream.
0

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/

Comments

-1

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());

4 Comments

@AAnuj Kumar Son have you seen this?
This is a bad solution - in such case you can easily avoid muting collection outside collection pipeline. As a rule of thumb you should avoid such constructs because of thread safety
@MichałMarcinkowski IMO it's better than create new object and waste time and resources! what do you think? anyway I updated my answer!
But it is insecure from a thread safety perspective, what if two threads try to modify the list in exactly the same time? To ensure that modifying outside collection will not break the program you have to synchronize list and operating on the synchronized list is in my opinion much more resource consuming than creating new List.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.