Java 8 Карта потоков против взгляда - PullRequest
2 голосов
/ 19 февраля 2020

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

List<String> alphabets = Arrays.asList(new String[]{"a","b","c"});         

List<String> upper1 = alphabets.stream().peek(l -> l.toUpperCase()).collect(Collectors.toList());        
upper1.forEach(System.out::println);         

List<String> upper2 = alphabets.stream().map(l -> l.toUpperCase()).collect(Collectors.toList());        
upper2.forEach(System.out::println);```

Output :-
a
b
c
A
B
C

1 Ответ

4 голосов
/ 19 февраля 2020

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

Пример того, как peek может использоваться в вашем коде :

List<String> alphabets = Arrays.asList(new String[]{"a","b","c"});         

List<String> upper = alphabets.stream()
           .peek(l -> System.out.println("Filtered value: " + l))
           .map(l -> l.toUpperCase())
           .peek(l -> System.out.println("Mapped value: " + l))
           .collect(Collectors.toList());
upper.forEach(System.out::println);

Это выводит:

Filtered value: a
Mapped value: A
Filtered value: b
Mapped value: B
Filtered value: c
Mapped value: C
A
B
C

В то время как результаты карты представляют собой поток результатов, применяющих данную функцию в пике, это просто исходный поток результатов. А поскольку строки в java являются неизменяемыми, выполнение функции не будет зависеть от выполнения функции.

Если бы элементы были ссылками (как объекты), а функция peek обновила содержимое этих ссылок, они бы были обновлены, но это не тот случай.

Пример просмотра с объектом MyString:

class MyString {
    String str;

    MyString(String str) {
        this.str = str;
    }

    public void toUpperCase() {
        str = str.toUpperCase();
    }

    @Override
    public String toString() {
        super.toString();
        return str;
    }
}

List<MyString> alphabets = Arrays.asList(new MyString[]{new MyString("a"), new MyString("b"), new MyString("c")});

List<MyString> upper = alphabets.stream()
        .peek(l -> l.toUpperCase())
        .collect(Collectors.toList());

upper.forEach(System.out::println);

полный код см. здесь:

http://tpcg.io/6GlwFizW

Вы можете видеть, что на выходе получается:

A
B
C

, так как в этом случае мы изменяем внутреннее состояние каждого элемента.

Обратите внимание, что я специально сделал, чтобы MyString.toUpperCase () возвратил void вместо объекта MyString, поэтому он не сможет работать с map таким образом.

...