Bring Class Leader Id on top of the list using Java8 Streams

Viewed 69

I have a list of students and I want to bring only the leaderId on top of the same list following remains the remaining list items using Java Streams. I tried the below logic but it is not working as expected

List<Student> students = ....

Long leaderId = 123;

students.stream().sort((s1,s2) -> leaderId.equals(s1.getId()) || leaderId.equals(s2.getId()) ? 1: 0).collect(Collectors.toList());

Can anyone please give me some suggestion on this

Example

List of students:

[{id:121, name:"John"}, {id:131, name:"Susan"}, {id:123, name:"Jacob"}, {id:155, name:"Sunny"}]

Expected Output

[{id:123, name:"Jacob"}, {id:121, name:"John"}, {id:131, name:"Susan"}, {id:155, name:"Sunny"}]
2 Answers

You have to write your own comparator first which places the leader at the front of the list when sorted using it. Then you have to use it for sorting the list. I don't see any point of using the streams here, since the iterative code looks more simple and readable. Here's how it looks in practice.

static class LeaderFirstComparator implements Comparator<Student> {
    final long leaderId;

    LeaderFirstComparator(long leaderId) {
        this.leaderId = leaderId;
    }

    @Override
    public int compare(Student o1, Student o2) {
        if (o1.id == leaderId && o2.id != leaderId)
            return -1;
        else if (o1.id != leaderId && o2.id == leaderId)
            return 1;
        else
            return 0;
    }

}

And the client code:

students.sort(new LeaderFirstComparator(leaderId));

Update

If the first object is the leader, then it should come before the second, hence returning -1 according to the contract. Otherwise, if the second object is the leader, then the first one should come after it, hence 1. If nether of the objects are the leader or both are leaders, then the original ordering is preserved. Thus returning 0.

As per the below comment, you can further simplify it to this one liner:

students.sort(Comparator.comparing(s -> s.getId() != leaderId));

If the leader has a concrete id equals to 123, yo can get it using only a filter

List leaderStudents = students.stream().filter(s1 -> leaderId.equals(s1.getId()).collect(Collectors.toList());
Related