Dúvida sobre Stream e Lambda

Estou querendo imprimir o seguinte:

Lista de Pessoas
Qtd de Pessoas: 4
Nome: Bruna
Nome: Maria
Nome: Paulo
Nome: Roberto

Fiz o seguinte código:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamLambdaTest {
	static class Pessoa {
		String nome;

		public Pessoa(String nome) {
			super();
			this.nome = nome;
		}

		@Override
		public String toString() {
			return nome;
		}
	}

	public static void main(String[] args) {
		List<Pessoa> listaDePessoa = Arrays
		    .asList("Paulo", "Maria", "Roberto", "Bruna").stream()
		    .map(Pessoa::new)
		    .collect(Collectors.toList());

		StringBuilder stringBuilder = new StringBuilder("Lista de Pessoas")
		    .append("\nQtd de Pessoas: ")
		    .append(listaDePessoa.size());

		listaDePessoa.stream().map(Pessoa::toString).sorted()
		    .forEach(stringBuilder.append("\nNome: ")::append);

		System.out.println(stringBuilder);
	}
}

mas está imprimindo:

Lista de Pessoas
Qtd de Pessoas: 4
Nome: BrunaMariaPauloRoberto

gostaria de saber o porquê de não estar imprimindo da forma que eu queria.

Veja, somente quem vem após :: entra no loop de fato.

Use:

lista.stream()
    .map(Pessoa::getNome)
    .sorted()
    .forEach(nome -> info.append("\nNome: ").append(nome));
List<Pessoa> listaDePessoa = Arrays.asList("Paulo", "Maria", "Roberto", "Bruna")
                                   .stream()
                                   // para cada nome você vai instanciar uma Pessoa com aquele nome
                                   .map(nome -> new Pessoa(nome))
                                   .collect(Collectors.toList());

StringBuilder stringBuilder = new StringBuilder("Lista de Pessoas")
                                 .append("\nQtd de Pessoas: ")
                                 .append(listaDePessoa.size());

listaDePessoa.stream()
             .map(Pessoa::toString) // na sua implementação o toString() retorna o nome
             .sorted()
             .forEach(nome -> stringBuilder.append("\nNome: ").append(nome));

System.out.println(stringBuilder);

Isso eu já sabia.

O que não estava entendo o motivo de estar imprimindo daquele jeito.

Acreditava que

.forEach(stringBuilder.append("\nNome: ")::append);

e

.forEach(nome -> stringBuilder.append("\nNome: ").append(nome));

tivessem o mesmo efeito.

Mas agora já entendi o motivo. O stringBuilder.append("\nNome: ") é executado uma vez antes da execução do foreach, então suponho que o que fiz, fosse equivalente a:

StringBuilder stringBuilderStream = stringBuilder.append("\nNome: ");
listaDePessoa.stream()
             .map(Pessoa::obterNome) 
             .sorted()
             .forEach(nome -> stringBuilderStream.append(nome));
1 curtida