내가 스트림을 가지고 있고 스트림 중간에 “풍부하게”하고 싶다고 가정 해 보겠습니다 peek()
. 예를 들면 다음과 같습니다.
streamOfThings.peek(this::thingMutator).forEach(this::someConsumer);
코드에서이 시점에서 Things를 변경하는 것이 올바른 동작이라고 가정합니다. 예를 들어, thingMutator
메소드는 “lastProcessed”필드를 현재 시간으로 설정할 수 있습니다.
그러나 peek()
대부분의 상황에서 “보이지만 만지지 마십시오”를 의미합니다.
스트림 요소 peek()
를 음소거 하는 데 사용 하는 것이 반 패턴이거나 잘못 권장됩니까?
편집하다:
보다 전통적인 대안은 소비자를 전환하는 것입니다.
private void thingMutator(Thing thing) {
thing.setLastProcessed(System.currentTimeMillis());
}
매개 변수를 반환하는 함수로
private Thing thingMutator(Thing thing) {
thing.setLastProcessed(currentTimeMillis());
return thing;
}
사용이 map()
대신 :
stream.map(this::thingMutator)...
그러나 그것은 perfunctory 코드 ( return
) 를 소개 peek()
하며 동일한 객체를 반환한다는 것을 알고 있기 때문에 더 명확하다고 확신 하지는 않지만 map()
동일한 클래스 의 객체 라는 것을 한눈에 알 수는 없습니다 .
또한, peek()
당신은 돌연변이 람다를 가질 수 있지만 map()
, 기차 난파선을 만들어야합니다. 비교:
stream.peek(t -> t.setLastProcessed(currentTimeMillis())).forEach(...)
stream.map(t -> {t.setLastProcessed(currentTimeMillis()); return t;}).forEach(...)
나는 peek()
버전이 더 깨끗하고 람다는 분명히 변하고 있다고 생각 하므로 “신비한”부작용은 없다. 유사하게, 방법 참조가 사용되고 방법의 이름이 돌연변이를 분명히 암시한다면, 그것도 분명하고 명백하다.
개인적으로, 나는 peek()
돌연변이 를 사용하여 부끄러워하지 않습니다 . 매우 편리합니다.
답변
영어 단어의 의미에서 “피킹”은 “보이지만 만지지 마십시오”를 의미합니다.
그러나 의 JavaDoc의 상태 :
몰래 엿보다
스트림 엿보기 (소비자 행동)
이 스트림의 요소로 구성된 스트림을 리턴하고 결과 스트림에서 요소가 소비 될 때 각 요소에 대해 제공된 조치를 추가로 수행합니다.
핵심 단어 : “수행 중 … 작업”및 “소비”. JavaDoc은 peek
스트림을 수정할 수있는 능력이 있어야한다는 점을 분명히 알고 있습니다.
그러나 JavaDoc은 또한 다음과 같이 말합니다.
API 참고 사항 :
이 방법은 주로 디버깅을 지원하기 위해 존재하며 파이프 라인의 특정 지점을지나 가면서 요소를 확인하려는 경우
이것은 예를 들어 스트림의 요소 로깅과 같은 관찰을위한 것임을 나타냅니다.
이 모든 것에서 취한 것은 스트림의 요소를 사용 하여 작업 을 수행 할 수 있지만 스트림의 요소를 변경 하지 않아야한다는 것 입니다. 예를 들어, 객체에 대해 메소드를 호출하지만 객체에 대한 조작을 피하십시오.
최소한 다음 줄을 따라 코드에 간단한 주석을 추가합니다.
// Note: this peek() call will modify the Things in the stream.
streamOfThings.peek(this::thingMutator).forEach(this::someConsumer);
이러한 의견의 유용성에 대한 의견은 다르지만이 경우 그러한 의견을 사용합니다.
답변
쉽게 잘못 해석 될 수 있으므로 이와 같이 사용하지 않는 것이 좋습니다. 아마도 가장 좋은 옵션은 람다 함수를 사용하여 필요한 두 동작을 forEach 호출에 병합하는 것입니다. 기존 객체를 변경하지 않고 새 객체를 반환하는 것을 고려할 수도 있습니다. 약간 덜 효율적이지만 더 읽기 쉬운 코드가 생성 될 수 있으며 수정 된 목록을 사용해야하는 다른 작업에 실수로 수정 된 목록을 사용할 가능성이 줄어 듭니다. 원본을 받았습니다.
답변
API 노트는이 메소드가 디버깅 / 로깅 / 발사 통계 등과 같은 작업에 주로 추가되었음을 알려줍니다.
@apiNote이 방법은 주로 디버깅을 지원하기 위해 존재합니다. 여기서 파이프 라인의 특정 지점을지나 가면서 요소를 볼 수 있습니다. *
{@암호 * Stream.of ( "1", "2", "3", "4") * .filter (e-> e.length ()> 3) * .peek (e-> System.out.println ( "필터링 된 값 :"+ e)) * .map (문자열 :: toUpperCase) * .peek (e-> System.out.println ( "매핑 된 값 :"+ e)) * .collect (Collectors.toList ()); *}