2017-11-17 1 views
1

Stream.peek 작업을 사용하고있는 다른 Stackoverflow question 나왔다 솔루션을 작동하지만 여전히 상태를 변경하기 때문에 오른쪽 같지 않습니다. Stream.peek 방법.Stream.peek 상태 변경 가능한 부작용 및이 같은 사용하지 왜

내가 여전히 Stream.peek합니다 (Stream의 소스 모음의 상태를 포함) 상태를 변이 안된다는 완전히 확신하지 않다 상태를 돌연변이 확인 여부 Stream.peek 사용에 (herehere)를 연구하는 동안.

이 방법은 당신이 그들이 파이프 라인에서 특정 지점을지나 흐름으로 요소를보고 싶은 경우 주로 디버깅을 지원하기 위해 존재 : 여기

Javadoc의 말씀입니다

그런 다음 :

매개 변수 : 작업 - a 간섭 없음 요소가 스트림에서 소비 될 때 요소에서 수행 할 작업입니다.

잘 동작하는 비 간섭 스트림 소스에, 소스는 동작이 개시 단말 전에 변형 될 수 있으며, 이러한 변형이 반영된다 elements.All에게 JDK 모음에서 반환 스트림을 다루는 , 그리고 대부분 JDK 클래스는 이러한 방식으로 올바르게 동작합니다. 스트림의 컬렉션의 상태를 변경하지 포함 동작을 비 간섭처럼

보인다.

다음은 Stream.peek을 사용하는 코드입니다.

Map< String, List<Test> > userTests = new HashMap<>(); 

Map< String, List<Test> > filtered = userTests.entrySet().stream() 
     .peek(e -> e.setValue(modifyListAndReturnIt(e.getValue()))) 
     .filter(e -> !e.getValue().isEmpty()) //check if modified list in peek has been emptied 
     .collect(Collectors.toMap(p -> p.getKey(), p -> p.getValue())); 

    public static List<Test> modifyListAndReturnIt(List<Test> list){ 
     if (somecondition) list.clear(); 
     return list; 
    } 

1) 위 코드에 부작용이 있습니까?

2) 그런 방식으로 peek을 사용하지 않는 이유는 무엇입니까? Javadoc은 그것을 허용하지 않는 것 같습니다.

+0

당신은 완전성에 대한 스트림 소스와 방법의 정의의 정의 스트림 파이프 라인 내에서 사용되는 표시 할 수 있습니다? 또한, 두 번째 질문에 대해서만 당신은 자기 자신에게 물어볼 필요가있다. "왜 그 방법이 디버깅 목적을위한 것인지는?" 그런 다음 "peek"메소드의 구현이 변경되면 자문 해보십시오. 내 코드는 어떻게됩니까? –

+1

내 조언은 당신이 항상하는 방법을이 사용하기위한 한 방법을 사용해야한다는 것입니다. 아무것도 더. –

+0

@ Aominè. 사실 Javadoc은 "오직"디버깅에 사용되어야한다고 말하지 않고 "대부분"은 "유일한 것"과 같지 않습니다. – tsolakp

답변

2

Brian Goetz가 comment here으로 말한 것처럼 은 해를 끼치 지 않습니다.로 보입니다.

이제 당신이 그 안에 부작용을 일으킨다면 -이 부작용이 실제로 일 때 일 것이라고 예상 할 수 있습니다. 그래서,이 같은 일부 개체의 일부 속성을 변경하려는 것입니다 가정 :

에서
myUserList.stream() 
      .peek(u -> u.upperCaseName()) 
      .count() 

자바-8 당신의 peek 실제로 9, 호출 할 것이다 - 그렇지 않다 - 때문에 여기 peek를 호출 할 필요가 없습니다 크기는 어쨌든 계산 될 수 있습니다.

동일한 경로에있는 동안, 터미널 작업이 findFirst 또는 findAny 같은 단락 하나라고 상상 - 당신은하지소스모든 요소를 ​​처리 할 것입니다 - 당신은 몇 가지를 얻을 수 있습니다 그들의 파이프 라인을 통해.

터미널 작업이 단락 회로가 아니더라도 peek이 만남 명령에 의존한다면 상황이 더 이상 할 수 있습니다. 병렬 처리를위한 중간 연산은 만나는 순서를 가지지 만, 끝단 연산은 수행하지 않습니다. 당신이 직면 한 놀라움을 상상해보십시오.

+0

: https://stackoverflow.com/questions/33635717/in-java-streams-is-peek-really-only-for-debugging; 그것은 마치 내게 똑같은 것처럼 보입니다. 심지어 내 답변도 그 요약처럼 보입니다. | 불행하게도 이에 대한 명확한 답이 보이지 않는 – Eugene

+0

으로 많은 표가있는 경우 나 중복으로 닫습니다. 어떤 사람들은'peek'을 사용하지 않는다고 말합니다. 왜냐하면 이것은이 유형의 사용을 의도하지 않았기 때문에 사용하는 것이지만 아주 조심스럽게 사용할 수 있다고 말하는 사람들이 있습니다. 'peek'또는 잠재적으로 상태를 변경할 수있는'map'과 같은 다른 중간 작업에 대해서도 규칙의 일반적인 엄지 손가락을 정의 할 수없는 것처럼 보입니다. – tsolakp

+0

@tsolakp 당신은 어떤 식 으로든 옳습니다 - 나는 동의합니다. 이 경우 나는 공식적인 문서에 충실하고 그것이 말하는 것과 그것이 부작용이 나쁘다는 것을 분명히 말해줍니다. 물론 사람들은 어떤 식 으로든이를 악용하려고 시도 할 수도 있습니다. 여러분이 그면에 있기를 원한다면 전적으로 당신에게 달려 있습니다. – Eugene