Почему редактирование списка с помощью фильтра потоковых данных работает? - PullRequest
0 голосов
/ 28 марта 2019

Я сделал некоторый кусок кода, который я не понимаю, почему он работает, и я не могу найти четкого ответа.Вот мой код:

    log.debug("before");
    for (Employee e : this.employees) {
        log.debug(e.toString());
    }
    employees
            .stream()
            .filter(e -> e.getUuid().equals(event.getEmployeeUuid()))
            .peek(e -> {
                e.setPosition(event.getPosition());
            }).collect(Collectors.toList());
    log.debug("after");
    for (Employee e : this.employees) {
        log.debug(e.toString());
    }

и вот вывод:

before
Employee(uuid=aaa, position=Lord)
Employee(uuid=bbb, position=Employee)
after
Employee(uuid=aaa, position=Overlord)
Employee(uuid=bbb, position=Employee)

Итак, мой общий вопрос: почему это работает?Я заметил это поведение случайно, и оно работает только тогда, когда .collect(Collectors.toList()) присутствует в конце обработки потока.Обратите внимание, что нет явного назначения вывода потока в список this.employees.

1 Ответ

1 голос
/ 30 марта 2019

Ваш employees список содержит ссылок на каждый Employee элемент. Поток просто перебирает эти ссылки и помещает их в конвейер. Ваша операция peek имеет побочный эффект изменения свойства позиции каждого Employee, разрешенного через filter. Везде, где у вас есть ссылка на эти Employee экземпляры, вы увидите эту модификацию, включая первоначальный список employees. Для получения дополнительной информации см. Является ли Java «передачей по ссылке» или «передачей по значению»? .

Причина, по которой вы не увидели никаких изменений, пока не добавили вызов к collect, заключается в том, что collect является терминальной операцией , тогда как filter и peek не. Stream не будет выполняться, пока не будет запущена терминальная операция.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...