Могу ли я сказать, что метод peek () в java.util.stream.Stream должен быть идемпотентным - PullRequest
0 голосов
/ 29 апреля 2018

Мой вопрос связан с: Что означает идемпотентный метод и каковы побочные эффекты в случае вызова метода close из java.lang.AutoCloseable?

Что касается метода в java.util.stream.Stream.peek(), в книге Oracle Certified Professional Java SE 8 Учебное пособие> глава 4 Функциональное программирование> Использование потоков> Использование общих промежуточных операций было указано, что peek () предназначен для выполнить операцию без изменения результата

Мой вопрос : могу ли я на практике сказать , действие в процессе просмотра (действие потребителя) должно быть идемпотентным , хотя код с сохранением состояния в peek() может скомпилировать?

Ответы [ 2 ]

0 голосов
/ 15 мая 2018

Javadoc говорит, что это должно быть не мешающим , а не идемпотентным, что не одно и то же.

На самом деле, поскольку он не должен мешать и может действовать только через побочные эффекты, вполне вероятно, что он не идемпотентен.

Примечание API даже ясно показывает пример неидемпотентного использования:

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

Stream.of("one", "two", "three", "four")
    .filter(e -> e.length() > 3)
    .peek(e -> System.out.println("Filtered value: " + e))
    .map(String::toUpperCase)
    .peek(e -> System.out.println("Mapped value: " + e))
    .collect(Collectors.toList());

Как вы знаете, System.out.println() не идемпотентен, поскольку каждый вызов создает новую строку вывода.

0 голосов
/ 29 апреля 2018

Вы не должны этого делать, потому что это может означать, что операция может изменить конечный результат, потому что идемпотентная операция может изменить объект, на котором она работает .

В следующем примере используется идемпотентная операция внутри метода peek(), но изменяет результат (что не является хорошей практикой в ​​соответствии с указанной вами документацией)

import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

class SomeClass {

    private String state = "some-value";

    public void idempotent() {
        state = "other-value";
    }


    @Override
    public String toString() {
        return "SomeClass{" +
                "state='" + state + '\'' +
                '}';
    }
}

public class Idempotent {

    public static void main(String[] args) {
        Set<SomeClass> collect = Stream.of(new SomeClass(), new SomeClass())
                .peek(SomeClass::idempotent)
                .collect(Collectors.toSet());
        System.out.println(collect);
    }
}

До операции peek() поток состоит из ["some-value", "some-value], а после peek() с идемпотентной операцией он состоит из ["other-value", "other-value"].

...