Java 8 Streams: условия, чтобы избежать повторения? - PullRequest
0 голосов
/ 12 октября 2018

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

    List<String> alist = new ArrayList<>();
    alist.add("hello");
    alist.add("hello2");

    if(verbose) {
        alist.stream()
                .peek(System.out::println)
                .forEach(/*dostuff*/);
    }
    else {
        alist.stream().forEach(/*dostuff*/);
    }

Как видно выше, я вынужден повторитьобработка потока в случае if или else, которая выглядит несколько уродливо, если поток становится немного длиннее.

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

    List<String> alist = new ArrayList<>();
    alist.add("helllo");
    alist.add("hello2");

    alist.stream()
            .peek(this::printVerbose)
            .forEach(/*dostuff*/);

}


private void printVerbose(String v) {
    if(verbose) {
        System.out.println(v);
    }

}

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

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

public static <T> Consumer<? super T> logIfNeeded(boolean verbose) {
    return verbose ? System.out::println : t -> { };
}

Затем в конвейере потока:

alist.stream()
        .peek(logIfNeeded(verbose))
        .forEach(/*dostuff*/);

Разница с вашим вторым подходом заключается в том, что флаг не проверяется для каждого элемента;действие выбирается охотно, когда статический метод вызывается при объявлении потокового конвейера.

0 голосов
/ 12 октября 2018

Вы можете сделать что-то вроде этого:

    Stream<Integer> stream = alist.stream();
    if(verbose) {
        stream = stream
                .peek(System.out::println);
    }
    stream.forEach(/*dostuff*/);
...