#java #java-stream
Вопрос:
У меня есть список следующих объектов,
ArrayList<Student> students = new ArrayList<>(
List.of(
Student.builder().id(1L).name("Joe").build(),
Student.builder().id(2L).name("Jan").build()
)
);
Я хочу обновить один из этих объектов, и у меня есть следующая реализация
return findAll().stream()
.filter(s -> s.getId() == studentId)
.map(s -> students.set(students.indexOf(s), Student.builder().id(s.getId()).name(studentPayload.getName()).build()))
.findFirst()
.orElseThrow(() -> new StudentNotFoundException(String.format("Student with id [%d] not found", studentId)));
Это возвращает объект, который удовлетворяет условию, основанному на filter
. К сожалению, это не самый современный объект!
Как я могу получить обновленный объект после сопоставления?
Комментарии:
1. Кажется, что сложность возникает в результате усилий, направленных на то, чтобы сделать его единым. Эта проблема в значительной степени исчезнет, если вы отфильтруете, чтобы найти свой объект, а затем обновите его как отдельные инструкции… и полученный код был бы более читабельным!
2. Переопределяет ли тип вашего построенного
Student
объектаequals()
иhashCode()
?3. Эмпирическое правило: если вы имеете дело не более чем с одним элементом, не используйте потоки.
4. Привет @AmalK, да, это так.
Ответ №1:
Это связано с тем, что set
метод a List
вернет ПРЕДЫДУЩИЙ элемент в этой позиции, а не вновь созданный. Ссылаться
Предполагая, что ваше идентификационное значение уникально, я не думаю, что это удобно использовать map
, а затем findFirst
, даже если вы могли бы достичь желаемого результата.
Вместо этого используйте findFirst
и получите элемент, а затем обновите детали в качестве второго шага.
Student sOne = findAll().stream()
.filter(s -> s.getId() == studentId)
.findFirst()
.orElseThrow(() -> new StudentNotFoundException(String.format("Student with id [%d] not found", studentId)));
Student sTwo = students.get(students.indexOf(sOne));
if(sTwo!=null) {
sTwo.setName(studentPayload.getName());
}
return sTwo;
Если вы все еще хотите сделать это в одну строку, то используйте:
map(s -> {
Student stu = students.get(students.indexOf(s));
stu.setName(studentPayload.getName());
return stu;
}
Комментарии:
1. Насколько я понимаю код в вопросе, он обновляет как соответствующий объект из
findAll()
списка, так и соответствующий объект изstudents
. Я думаю, что этот код будет обновлять только первый.2. @ernest_k Да, я как-то пропустил эту
findAll
часть (я обновил свой ответ). Но обновляется только объект изstudents
, верно?3. Ах, вы правы. Только
students
обновляется.