Потоки / карты / фильтры Java 8 для изменения или удаления элементов списка «на лету»

#java #java-8 #java-stream

#java #java-8 #java-stream

Вопрос:

Java 8 здесь. Ищу (возможно, основанный на потоке) «Java 8» способ замены и / или удаления объекта из List . Вот мой код:

 public void applyChanges(List<Fizz> fizzes, Action action, Fizz toModify) {
  int i = 0;
  for (Fizz fizz : fizzes) {
    i  ;
    if (fizz.getId() == toModify.getId()) {
      switch(action) {
      case Replace:
        // Here we want to replace 'fizz' in the list
        // with 'toModify' however order/sequence doesn't matter.
        fizzes.remove(i);
        fizzes.add(toModify);
        break;
      case Delete:
      default:
        // Here we just want to remove the Fizz with the matching
        // ID from 'fizzes'.
        fizzes.remove(i);
        break;
      }
    }
  }
}
  

Я думаю, что это можно написать более эффективно / лаконично, а также таким образом, чтобы использовать потоки / карты Java 8, но, похоже, я не могу понять, как соединить все вместе. Есть идеи?

Ответ №1:

Поскольку вы используете void в качестве возвращаемого типа и хотите изменить данный список с помощью потока, это было бы не лучшим решением. Вы можете просто использовать List.replaceAll() и List.removeIf() для решения этой проблемы с помощью простого if заявления:

 public void applyChanges(List<Fizz> fizzes, Action action, Fizz toModify) {
    if (action == Action.Replace) {
        fizzes.replaceAll(fizz -> fizz.getId() == toModify.getId() ? toModify : fizz);
    } else {
        fizzes.removeIf(fizz -> fizz.getId() == toModify.getId());
    }
}
  

Если у вас есть больше действий, чем replace и delete, вы можете использовать switch оператор вместо if .

Если вы действительно хотите использовать потоки, я бы также разделил различные действия. Вы также должны вернуть новый список в свой метод и переназначить его переменной, которую вы передаете этому методу:

 public List<Fizz> applyChanges(List<Fizz> fizzes, Action action, Fizz toModify) {
    if (action == Action.Replace) {
        return fizzes.stream()
                .map(fizz -> fizz.getId() == toModify.getId() ? toModify : fizz)
                .collect(Collectors.toList());
    }
    return fizzes.stream()
            .filter(fizz -> fizz.getId() != toModify.getId())
            .collect(Collectors.toList());
}
  

Ответ №2:

Вы можете использовать map с потоками что-то вроде :

 List<Fizz> applyChanges(List<Fizz> fizzes, Action action, Fizz toModify) {
    return fizzes.stream()
            .map(fizz -> fizz.getId().equals(toModify.getId()) ?
                    action.equals(Action.Replace) ? toModify : null : fizz)
            .filter(Objects::nonNull)
            .collect(Collectors.toList());
}
  

Комментарии:

1. Основано на предположении о текущем использовании switch и потребует соответствующего обновления.