기존 스트림에 새로운 가치 추가


79

기존에 새로운 가치를 추가하는 좋은 방법이 Stream있습니까? 내가 상상할 수있는 것은 다음과 같다.

public <T> Stream<T> addToStream(Stream<T> stream, T elem ) {
    List<T> result = stream.collect(Collectors.toList());
    result.add(elem);
    return result.stream();
}

그러나 나는 장황함없이 람다 표현에서 사용할 수있는 더 간결한 것을 찾고 있습니다.

PECS 원칙 을 구현하려고 할 때 또 다른 질문이 나타났습니다 .

public <T> Stream<? super T> addToStream(Stream<? super T> stream, T elem ) {
    List<? super T> result = stream.collect(Collectors.toList()); //error
    result.add(elem);
    return result.stream();
}

와일드 카드가 작동하지 않는 것 같고 Stream.collect이유가 궁금합니다. 미리 감사드립니다.


2
이 지원 에서 List반환 된다는 보장은 없습니다. 대신 사용할 목록 유형을 선택할 수 있습니다. collect(Collectors.toList())addCollectors.toCollection
Alex-GlassEditor.com 2015

답변:


97

문제는 잘못된 가정에 있습니다. 즉, 스트림에 실제로 데이터가 포함되어 있습니다. 그들은하지 않습니다; 스트림은 데이터 구조가 아니며 다양한 데이터 소스에서 대량 작업을 지정하는 수단입니다.

두 개의 스트림을 하나로 결합하기위한 결합 자 (예 Stream.concat:)와 알려진 요소 세트 ( Stream.of) 또는 컬렉션 ( Collection.stream) 에서 스트림을 생성하기위한 팩토리가 있습니다. 따라서 새로운 요소를 설명하는 새 스트림과 함께 손에 들고있는 스트림의 연결 인 새 스트림을 생성하려면 이들을 결합 할 수 있습니다.

PECS 예제의 문제점은 세 개의 발생이 ? super T있고 동일한 유형을 설명한다고 가정하지만 그렇지 않다는 것입니다. 와일드 카드의 각 항목은 고유 한 캡처에 해당하며 원하는 것이 아닙니다. 컴파일러가 목록의 유형과 입력 스트림의 유형이 동일하다는 것을 알 수 있도록 해당 유형 변수에 이름을 지정해야합니다. (또한 컬렉션을 구체화하지 마십시오. 비용이 많이 들고 스트림이 유한하지 않은 경우 종료되지 않을 수 있습니다. concat을 사용하십시오.) 따라서 대답은 : 방금 제네릭이 잘못되었습니다. 이를 수행하는 한 가지 방법은 다음과 같습니다.

public<T> Stream<T> appendToStream(Stream<? extends T> stream, T element) {
    return Stream.concat(stream, Stream.of(element));
}

실제로 스트림에서 소비하고있을 때 스트림에 "삽입"을 고려하고 있었기 때문에 PECS와 혼동했습니다.


7
메서드 이름이 "appendToStream"이면 안됩니까? 그렇지 않으면 concat 메소드의 매개 변수가 전환되어야한다고 생각합니다.
Andrea Polci

concat메소드는 javadoc에서 사용할 수 있지만 많이 사용할 수는 없습니다. 반복 된 연결에서 스트림을 구성 할 때주의하십시오. 깊게 연결된 스트림의 요소에 액세스하면 깊은 호출 체인 또는 StackOverflowException이 발생할 수 있습니다.
TongChen

34

어때

return Stream.concat(stream, Stream.of(elem));

이것은 원래 스트림이 유한하다고 가정합니다. 그렇지 않은 경우 역순으로 연결할 수 있습니다.


반복 된 연결에서 스트림을 구성 할 때주의하십시오. 깊게 연결된 스트림의 요소에 액세스하면 깊은 호출 체인 또는 StackOverflowException이 발생할 수 있습니다.
TongChen

5

StreamEx의 라이브러리는 대응하고있다 #prepend()#append()방법에 관한 것이다. 다음은 사용 방법의 예입니다.

StreamEx.of("second").prepend("first").append("third").forEach(System.out::println);

출력은 다음과 같습니다.

first
second
third

좋은! 그러나 다른 도서관.
GhostCat

0

가장 좋은 방법은 다음과 같이 flatMap을 사용하는 것입니다.

public <T> Stream<T> appendToStream(Stream<T> stream, T element) {
    return stream.flatMap(e -> Stream.of(e, element));
}

이것은 원래 스트림에서 작동하므로 스트림에서 또 다른 중간 작업이 될 수 있습니다. 예 :

    stream.flatMap(e -> Stream.of(e, element))
            .map(...)
            .filter(...)
            .collect(Collectors.toList());

요소를 몇 번 추가 하시겠습니까? : D Ounce for stream 또는 one per element in original stream?
user482745
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.