#java #sorting #java-8 #java-stream
Вопрос:
У меня есть список студентов, и я хочу, чтобы в верхней части того же списка был указан только идентификатор лидера, после чего остаются остальные элементы списка с использованием потоков Java. Я попробовал нижеприведенную логику, но она работает не так, как ожидалось
List<Student> students = ....
Long leaderId = 123;
students.stream().sort((s1,s2) -> leaderId.equals(s1.getId()) || leaderId.equals(s2.getId()) ? 1: 0).collect(Collectors.toList());
Может ли кто-нибудь, пожалуйста, дать мне какое-нибудь предложение по этому поводу
Пример
Список студентов:
[{id:121, name:"John"}, {id:131, name:"Susan"}, {id:123, name:"Jacob"}, {id:155, name:"Sunny"}]
Ожидаемый Результат
[{id:123, name:"Jacob"}, {id:121, name:"John"}, {id:131, name:"Susan"}, {id:155, name:"Sunny"}]
Ответ №1:
Сначала вы должны написать свой собственный компаратор, который помещает лидера в начало списка при его сортировке. Затем вы должны использовать его для сортировки списка. Я не вижу смысла использовать потоки здесь, так как итерационный код выглядит более простым и читаемым. Вот как это выглядит на практике.
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 amp;amp; o2.id != leaderId)
return -1;
else if (o1.id != leaderId amp;amp; o2.id == leaderId)
return 1;
else
return 0;
}
}
И клиентский код:
students.sort(new LeaderFirstComparator(leaderId));
Обновить
Если первый объект является лидером, то он должен прийти раньше второго, следовательно, возвращая -1 в соответствии с контрактом. В противном случае, если второй объект является лидером, то первый должен следовать за ним, следовательно, 1. Если нижний из объектов является лидером или оба являются лидерами, то первоначальный порядок сохраняется. Таким образом, возвращается 0.
Согласно приведенному ниже комментарию, вы можете еще больше упростить его до этого лайнера:
students.sort(Comparator.comparing(s -> s.getId() != leaderId));
Комментарии:
1. Спасибо за ответ, не могли бы вы объяснить, что означает -1, 1, 0 в контексте сопоставления идентификатора с идентификатором лидера
2. В вашем компараторе есть ошибка. Если оба
Student
объекта имеют совпадающий идентификаторleaderId
, компаратор должен возвращать ноль. Но обратите внимание, чтоBoolean
это сопоставимый тип (false < true
), поэтому вы можете просто использоватьstudents.sort(Comparator.comparing(s -> s.getId() != leaderId));
в целом,Comparator.comparing…
фабрики предпочтительнее, поскольку они избегают таких ошибок.3. Хороший улов, я обновил свой ответ. Пожалуйста, взгляните. Спасибо.
4. Да, теперь все правильно. Но использовать
Comparator.comparing(s -> s.getId() != leaderId)
все равно было бы проще.
Ответ №2:
Если у лидера конкретный идентификатор равен 123, вы можете получить его, используя только фильтр
List leaderStudents = students.stream().filter(s1 -> leaderId.equals(s1.getId()).collect(Collectors.toList());
Комментарии:
1. Спасибо за ответ, но это возвращает только лидера в список, на самом деле я хочу, чтобы элемент лидера находился в начале того же списка, после чего остаются остальные элементы списка
2. Я привел один пример, показывающий пример использования