We have a Student class, having an int, a String (the name) and a double data member. We want read a bunch of Students from a data stream, sort them by the double - decreasing, then string, and then int. In the end we'll output just the student names.
This apparently boring little HackerRank problem shows how much more fun is Java since functional programming has been introduced in it.
I won't even talk about setting up the scanner and reading the 'count' number of students expected, and I focus here on the action.
Stream.generate(() -> new Student(sc.nextInt(), sc.next(), sc.nextDouble())) // 1 .limit(count) // 2 .sorted(Comparator // 3 .comparingDouble(Student::getCgpa).reversed() // 4 .thenComparing(Student::getFname) // 5 .thenComparingInt(Student::getId)) // 6 .map(Student::getFname) // 7 .forEach(System.out::println); // 8
- The stream comes up by data provided on the fly, reading them from the scanner - named sc. I read an int, a string, a double from it, I shovel them in the Student ctor, that is used in a lambda as supplier for the stream generated() method
- I don't want generate() to be called forever, the stream size is limited by the number of students, that I have previously read in 'count'
- I have to sort my stream, to do that I provide a Comparator ...
- Firstly I compare (primitive) doubles as provided by the Student.getCgpa() method. But, wait, I don't want the natural order, so I reverse it
- Second level of comparison, the Student first name
- Third level, the (primitive) int representing the Student id should be used
- Almost done. I'm interested in just the names, so I extract them by mapping
- Loop on the sorted student names, and print each one on a new line
You could get the full Java code from GitHub.