자바에서 스트림 정말 디버깅만 peek은?
나는 자바 스트림에 대해 그리고 나는 내가 진행함에 따라 새로운 것들을 발견하면서 책을 읽고 있습니다.나는 자바 스트림에 대해 그리고 나는 내가 진행함에 따라 새로운 것들을 발견하면서 책을 읽고 있습니다.제가 발견한 새로운 것은어느 나는 발견한새로운 일이다.peek()
기능.나는 유독 눈에 읽은 기능. 거의 모든 것이 당신의 시냇물 디버깅 하는 데 사용되어야 한다고 말한다.나는 유독 눈에 읽은 적이 거의 모든 것이 당신의 시냇물 디버깅 하는 데 사용되어야 한다고 말한다.
만약 내가 각 계정 사용자 이름, 암호장과 login()과 loggedIn()메서드가 있는 개울물 있었다.
나는이 있기도
Consumer<Account> login = account -> account.login();
그리고.
Predicate<Account> loggedIn = account -> account.loggedIn();
왜 이렇게 나쁜 짓이죠.
List<Account> accounts; //assume it's been setup
List<Account> loggedInAccount =
accounts.stream()
.peek(login)
.filter(loggedIn)
.collect(Collectors.toList());
이제 내가 그것 해야 할 수 있는 이 알 수 있다.,
- 계정의 목록을 감행한다.
- 각 계정에 로그온 하려고 하겠죠
- 어떤 구좌에서 로그인하지 않는 필터링 합니다.
- 새로운 목록에 계좌에 logged 수집합니다.
왜 이렇게 무언가를 하고 있는 그 단점은?나는 일어나지 않을 거 다른 이유가 있습니까?마지막으로, 아니면 이 해결책 나서는요?
이것의 원래 버전 다음과 같이;.filter()방법을 사용하였다.
.filter(account -> {
account.login();
return account.loggedIn();
})
당신은 이해할 수 있는 중요한 것 하천은 단말 조작에 의해 추구합니다.그 단말 조작 모든 요소를 반환하거나 전혀 가공되어야 한다를 결정한다.그렇게collect
항목을 처리하나 수술인 반면에,항목을처리하나 수술. 반면.findAny
예전에 그것이 일치하는 요소를 만났던 아이템을 처리 막도 될까.예전에 그것이 일치하는 요소를 만났던 아이템을 처리 막도 될까.
그리고 그리고.count()
그때 그것은 항목 처리하지 않고 스트림의 크기를 확인할 수 있는 요소들 모든에서 처리하지 않을 수 있다.그때 그것은 항목 처리하지 않고 스트림의 크기를 확인할 수 있는 요소들 모든에서 처리하지 않을 수 있다.이 있는 최적화 자바 8으로 만들어지지 않았지만, 자바 9에 있을 수 있고 본선에 진출할 때 여러분이 자바 9과 코드가 있이 있는에 의존하는 스위치 최적화 자바 8으로 만들어지지 않았지만, 자바 9에 있을 수 있고 본선에 진출할 때 여러분이 자바 9위에 의존하고수 있다 가질 코드를.count()
모든 아이템을 처리하다.모든 아이템을 처리하다.이것은 또한 다른implementation-dependent 세부 사항, 예에. 자바 9에서도 참조 구현 무한한 스트림 소스이것은또한다른implementation-dependent 세부 사항, 예에가 결합된 크기를 예측할 수 없을 것이다. 자바 9에서도 참조 구현 무한한 스트림 소스가 추정할 수 없을 것이다 연결되어 있다 연결되어 있다.limit
가 없지만 근본적인 한계 등 예측하지 못하고 있다.가 없지만 근본적인 한계 등 예측하지 못하고 있다.
이후 엿보다.“성분이 소비된다 결과 스트림에서 각 요소에 제공된 행동을”수 있게 해 줄 것은 하지만 단말 조작 필요에 따라 이 동작을 수행할 요소의 처리 의무화하지 않는다.This implies that you have to use it with great care if you need a particular processing, e.g. want to apply an action on all elements.이 단말 조작 모든 항목을 처리하기 위해서 보증하지만 그런다고 해도, 다음 개발자는 터미널 작업( 아니면 니가 미묘한 측면을 잊어 버리)을 바꾸도록 해야 할 일한다.
는 동안 스트림 작전의 평형 하천 심지어 하기 위해 일정한 조합의 조우를 질서를 유지할 것이라는 것을 또한 이러한 보증 또한에, 하천은 병렬 하천에 대해서도 일정한 조합의 운용을 위한 접선 질서를 유지하도록 보장하지만,이러한보증은 적용되지 않는다 적용되지 않는다.peek
때 목록에 수집, 결과 열거할 수도 있으나. 목록으로 수집할 때 결과 목록은 정렬된 병렬 스트림에 대한 올바른 순서를 갖지만 주문한 병렬 들어오는 스트림에 대해 올바른 순서를 가질 것이다.peek
액션은 임의의 순서에서 동시에 호출될 수도 있다.동작은 임의의 순서로 동시에 실행될 수 있다.
그래서그래서 당신이로 할 수 있는 가장 유용한 물건유용한 것은 가장수 있는 할.peek
스트림 요소는 API설명서는 것은 처리되었는지 확인:.스트림 요소가 처리되었는지 여부를 확인하는 것으로, API다음과같이정확하게 설명되어 있다 설명서에.
이 방법은 주로 디버깅을 지원하기 위해 존재하며, 여기서 요소가 파이프라인에서 특정 지점을 지나 흐를 때 해당 요소를 보려는 경우
이를 통해 얻을 수 있는 핵심 요소:
API가 즉각적인 목표를 달성하더라도 의도하지 않은 방식으로 사용하지 마십시오.그러한 접근방식은 미래에 깨질 수 있으며, 미래의 유지관리자들에게도 불명확하다.
이것을 여러 개의 운영으로 나눠도 별개의 운영이므로 해롭지 않다.API를 불명확하고 의도하지 않은 방식으로 사용하는 것은 해로우며, 이러한 특정 동작이 향후 자바 버전에서 수정될 경우 영향을 미칠 수 있다.
사용이 사용됩니다.forEach
이 작업에 대해 유지관리자는 각 요소에 의도된 부작용이 있음을 명확히 할 수 있다.accounts
그리곤다는 것을 돌변할 수 있는 일부 작업 공연을 하고 있다.돌연변이를 일으킬 수 있는 수술을 하고 있다는 겁니다
그것은 또한 더 의미에서도더 통속적이다 라는는 의미에서 인습적이다.peek
때까지 단말 조작 진행되는 전체 컬렉션에서 운용되지 않은 곳이 있는가 중간 수술이였다, 하지만중간 작업으로, 터미널 운영이 실행될 때까지 전체 수집에서 작동하지 않지만,.forEach
정말 말단 작전이야이런 식으로, 당신은 당신의 행동과 코드의 흐름을 둘러싸고 강한 논쟁을 할 수 있다.peek
로 …과행동할 것이다 똑같이 같은 행동할까.forEach
이런 맥락에서.이런 맥락에서 한다.
accounts.forEach(a -> a.login());
List<Account> loggedInAccounts = accounts.stream()
.filter(Account::loggedIn)
.collect(Collectors.toList());
아마도 경험 법칙은 "디버그" 시나리오 밖에서 엿보는 것을 사용하는 경우, 종료 및 중간 필터링 조건이 무엇인지 확신하는 경우에만 그렇게 해야 한다는 것이다.예를 들면 다음과 같다.
return list.stream().map(foo->foo.getBar())
.peek(bar->bar.publish("HELLO"))
.collect(Collectors.toList());
한 번의 작업으로 모든 Foos를 Bars로 변환하고 모든 인사말을 하는 것이 당신이 원하는 유효한 경우인 것 같다.
다음과 같은 것보다 더 효율적이고 우아해 보인다.
List<Bar> bars = list.stream().map(foo->foo.getBar()).collect(Collectors.toList());
bars.forEach(bar->bar.publish("HELLO"));
return bars;
컬렉션을 두 번 반복할 순 없어
나는저는그렇게 말할 거예요 말할 것이다.peek
모든 것을 터미널 방법으로 전달되는 단순하거나 구성 함수에 주입하는 대신 스트림 객체를 변이시킬 수 있는 코드를 분산하거나, 글로벌 상태를 수정(그것들에 기반)할 수 있는 기능을 제공한다.
이제 질문은 다음과 같을 수 있다: 스트림 객체를 변이해야 하는가, 기능적 스타일의 자바 프로그래밍에서 기능 내에서 글로벌 상태를 변화시켜야 하는가?
만약을 위의 2문제의 답은 예(또는:어떤 경우에는 그래)그때 위의 2개 질문 중 하나라도 예(또는:경우에 따라 예)인 경우.peek()
디버깅 목적으로만 사용되는 것은 아니다. 디버깅 목적으로만 사용되는 것은 아니다.
나에게 있을 때둘 중 사이에서 선택할 때때 나를 위해 선택할 하나를.forEach()
그리고 그리고.peek()
,:A다음을 선택하는 것이다 다음을 고르고 있다.또는 그들에게 직접 스트리밍 할 첨부하고 싶나 코드의 구성할 수 있는에 장착되는 스트림 개체 변형된 작품을 원하니?스트림 객체를 변이하는 코드 조각을 컴포지티브에 연결하시겠습니까,아니면스트림에 직접 연결하시겠습니까?
나는 생각합니다 것 같아peek()
더 java9 방법으로. 예를 들어 예를 들어, Java9 방법과 더잘 결합할 것이다와 짝을 이룰 것이다.takeWhile()
때 반복 이미 돌연변이 개체를 기반으로 하는 것을 막기 위해 결정할 것 그렇게 이미와 변이된 객체에 따라 반복을 중지할 시기를 결정해야 할 수 있으므로,이 경우가 껍질을 벗기고 필요할텐데.forEach()
같은 효과를 준다.같은 효과를 거두지못할 것이다.
P.S. 나는 언급하지 않았다.map()
아무 곳이나 상관 없기 때문에 경우에는 우리가(또는 세계적인 상태), 새로운 개체를 생성하는 것보다 개체 변형시키는을 원한다면, 그것은 우리가 물체(또는 글로벌 상태)를 변이시키고자 하는 경우, 새로운 물체를 생성하기 보다는 정확히 같은 방식으로 작동하기 때문에 어디에서나와 정확히 똑같이 기능하다.peek()
.
위의 대부분의 답변에는 동의하지만, 피크를 사용하는 것이 실제로 가장 깨끗한 방법처럼 보이는 경우가 있다.
사용 사례와 마찬가지로 활성 계정에서만 필터링한 다음 이러한 계정에 대한 로그인을 수행한다고 가정하십시오.
accounts.stream()
.filter(Account::isActive)
.peek(login)
.collect(Collectors.toList());
Peek는 수집을 두 번 반복할 필요가 없는 상태에서 중복 호출을 방지하는 데 도움이 된다.
accounts.stream()
.filter(Account::isActive)
.map(account -> {
account.login();
return account;
})
.collect(Collectors.toList());
많은 답변이 좋은 지적을 해 주었고, 특히 마코토가 (수용)한 답변은 발생 가능한 문제를 상당히 상세하게 기술하고 있다.그러나 아무도 그것이 어떻게 잘못될 수 있는지 보여주지 않았다.
[1]-> IntStream.range(1, 10).peek(System.out::println).count();
| $6 ==> 9
출력 없음.
[2]-> IntStream.range(1, 10).filter(i -> i%2==0).peek(System.out::println).count();
| $9 ==> 4
출력 번호 2, 4, 6, 8.
[3]-> IntStream.range(1, 10).filter(i -> i > 0).peek(System.out::println).count();
| $12 ==> 9
출력 번호 1부터 9까지입니다.
[4]-> IntStream.range(1, 10).map(i -> i * 2).peek(System.out::println).count();
| $16 ==> 9
출력 없음.
[5]-> Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9).peek(System.out::println).count();
| $23 ==> 9
출력 없음.
[6]-> Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9).stream().peek(System.out::println).count();
| $25 ==> 9
출력 없음.
[7]-> IntStream.range(1, 10).filter(i -> true).peek(System.out::println).count();
| $30 ==> 9
출력 번호 1부터 9까지입니다.
[1]-> List<Integer> list = new ArrayList<>();
| list ==> []
[2]-> Stream.of(1, 5, 2, 7, 3, 9, 8, 4, 6).sorted().peek(list::add).count();
| $7 ==> 9
[3]-> list
| list ==> []
(알아듣는다.
예들은jshell(자바 15.0.2)에서 데이터((자바 15.0.2예는 jshell을 대체하)으로 실행되었으며, 사례(대체)를 모방하였다 사용데이터를 변환하는 변환하는 사용 사례 모의 운영하는 것이었다.System.out::println
타고에 의해list::add
예를 들어 역시 어떤 대답에)그리고 얼마나 많은 데이터 추가되었다 돌아온 일입니다.예를 들어, 일부 답변에서 수행된 것과 같이), 그리고 얼마나 많은 데이터가 추가되었는지 반환.현재 관찰하는( 같은 필터 또는 생략)요소 필터링 할 수 있는 작업 남아 있는 모든 요소의 처리 강요할 것처럼 보이지만, 될 필요 그렇게 지내지 않다.현재의 관찰은(필터나 스킵과 같이)요소를 필터링할 수 있는 어떤 조작이라도 나머지 모든 요소를 강제로 취급하는 것처럼 보이지만,그렇게유지될 필요는 없다.
에대한설명서를 노트에도 불구하고에 대한 설명서를 노트에도 불구하고..peek
그"메서드는 주로 디버깅을 지원하는 데"나는 일반적인 연관성을 갖고 있다고 생각합니다.설명서를"주로"라고 말하는 한은 그렇게 다른 활용 사례의 여지가 있다.그것은년이란 시간이 흘렀고, 이의 철거에 대해 추측이 내 의견은 무의미하다는 사용되지 않지 않다.
저는 세상에서 여전히 유효한 곳과 유용성이었습니다side-effectful 방법 처리해야 할 말할 것이다.는 부작용을 사용한다 하천에 많은 유효한 수술이 있다.많은 다른 대답에 언급되어 왔다, 제가 여기에 개체의 컬렉션에, 또는 레지스트리들을 가지고, 이것은 더 스트림에서 처리되는 개체에 깃발을 잡을 수 있겠습니다.스트림 처리할 때 로그 메시지를 만들고 말할 필요도 없다.
그래서 내가 마지막 그래서 내가 마지막에 모든 것을 추진하고 피한 아이디어를 별도의 스트림으로 운영된 개별 동작을 가지고 있도록 응원합니다에 모든 것을 추진하고 피한 아이디어를 별도의 스트림으로 운영된 개별 동작을 가지고 있도록 응원합니다..forEach
. 나는.나는 선호하는을 선호하는.peek
동등 동등에에.map
누가만 목적은 람다로, 부작용 메서드를 호출하는 외에 이 논쟁에서 통과된 귀환할 예정이다.누가만 목적은 람다로, 부작용 메서드를 호출하는 외에 이 논쟁에서 통과된 귀환할 예정이다. .peek
그게 안으로 들어간다 또한자마자 나는 이 작업을 접할 때와 나는 람다를 읽어야 할지 찾는 것이 필요하지도 못 합니다 나 뭐 했냐고.그게 안으로 들어간다 또한자마자 나는 이 작업을 접할 때와 나는 람다를 읽어야 할지 찾는 것이 필요하지도 못 합니다 나 뭐 했냐고.그런 의미에서 간결한, 코드의 가독성을 향상시키는 표현이다.그런 의미에서 간결한, 코드의 가독성을 향상시키는 표현이다.
때를 사용하는 나는 모든 고려 사항과 동의한다고 말했다..peek
예를 들어 그것에 사용되는 스트림의 단말 조작의 영향을 잘 알고 있다는 것.
기능 해결책 계정 개체 불변의를 만드는 것이다.그래서 account.login() 새로운 계정 개체를 반환해야 합니다.이것은 지도 작업 로그인 대신에 엿보기 위해 사용할 수 있는 것을 의미한다.
참조URL:https://stackoverflow.com/questions/33635717/in-java-streams-is-peek-really-only-for-debugging
'IT이야기' 카테고리의 다른 글
봄에 시작할 때 메서드 실행한다. (0) | 2022.05.17 |
---|---|
농담이든+vuejs+vuetify과 예상치 못한 식별자입니다. (0) | 2022.05.17 |
Nuxt:js 파일에서vuex 상점에 액세스 할 수 없다. (0) | 2022.05.17 |
Java 스레드에 매개 변수를 전달하는 방법 (0) | 2022.05.16 |
코틀린에서 자바 정전기법에 해당하는 것은 무엇인가? (0) | 2022.05.16 |