왜 Itable 은 stream() 메서드와 parallel Stream() 메서드를 제공 하지 않습니까?
?가요?Iterable
는 「」를 .stream()
★★★★★★★★★★★★★★★★★」parallelStream()
합니다.하다
public class Hand implements Iterable<Card> {
private final List<Card> list = new ArrayList<>();
private final int capacity;
//...
@Override
public Iterator<Card> iterator() {
return list.iterator();
}
}
트레이딩 카드 게임을 하면서 카드를 손에 쥘 수 있는 핸드 구현입니다.
으로는 ★★★★★★★★★★★★★★★★★★★★★★★★.List<Card>
는 최대 용량을 확보하고 기타 유용한 기능을 제공합니다..List<Card>
.
했습니다.Iterable<Card>
하고 는 확장 할 수 루루 、 For - loops ) 。Hand
는 클래스도 합니다.get(int index)
즉 「」, 「」를 참조해 .Iterable<Card>
정당하다고 생각합니다.)
Iterable
는 다음interface 다 、 음음(( ( adoc ) 。
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
이제 다음을 사용하여 스트림을 얻을 수 있습니다.
Stream<Hand> stream = StreamSupport.stream(hand.spliterator(), false);
그럼 진짜 질문으로 넘어가죠.
- ?는 왜?
Iterable<T>
되어 있지 .stream()
★★★★★★★★★★★★★★★★★」parallelStream()
불가능하거나 원치 않는 건 아무것도 보이지 않아요?
제가 찾은 관련 질문은 다음과 같습니다.Stream이 필요한 이유<T > 구현 불가능 <T >
그건 이상하게도 어느 정도 다른 방법으로 할 수 있다는 것을 암시하는 것이다.
이는 누락이 아니었다. 2013년 6월에 EG 목록에 대한 자세한 논의가 있었다.
Expert Group의 최종적인 논의는 이 스레드에 뿌리를 두고 있습니다.
',stream()
가 있는 것 Iterable
「 」라는 사실.Iterable
이치노'CHANGE: 'CHANGE: 'CHANGE:
Stream<T> stream()
항상 네가 원하는 건 아니었어몇 가지 일은Iterable<Integer>
스트림 메서드가 반환되는 것이 더 낫습니다.IntStream
★★★★★★★★★★★★★★★★★★.stream()
이렇게 높은 계층에 있는 방법은 불가능하게 만들 수 있습니다. 그 정말 수 있게 요.Stream
Iterable
「」를spliterator()
★★★★★★★★의 실장stream()
Collection
을 사용하다
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
을 ""에서 얻을 수 .Iterable
라이선스:
Stream s = StreamSupport.stream(iter.spliterator(), false);
우리는 국, 리, 리를 더하는 것으로 을 내렸다.stream()
로로 합니다.Iterable
실수하는 거야
프로젝트 람다 메일링 리스트 중 몇 개를 조사했는데 흥미로운 논의를 몇 개 찾은 것 같아요.
나는 지금까지 만족할 만한 설명을 찾지 못했다.이 모든 것을 읽고 난 후 나는 그것이 단지 누락이라고 결론지었다.그러나 API 설계 과정에서 수년간 여러 번 논의된 것을 알 수 있습니다.
람다 립스 스펙 엑스퍼트
Lambda Libs Spec Experts 메일링 리스트에서 이에 대한 논의를 발견했습니다.
Itable/Iterator.stream()에서 Sam Pullara는 다음과 같이 말했습니다.
저는 Brian과 함께 제한/서브스트림 기능[1]을 구현하는 방법에 대해 알아보고 있었는데, 그는 Iterator로 전환하는 것이 올바른 방법이라고 제안했습니다.나는 그 해결책을 생각해 보았지만, 반복기를 가져와 스트림으로 만들 뚜렷한 방법을 찾지 못했다.이 안에 있는 것으로 판명되었습니다. 먼저 반복기를 스플리터로 변환한 다음 스플리터를 스트림으로 변환하기만 하면 됩니다.그래서 저는 이 두 가지를 Itable/Iterator 중 하나에 직접 매달아야 하는지 아니면 둘 다 매달아야 하는지에 대해 다시 생각하게 됩니다.
적어도 두 세계 사이를 깔끔하게 이동할 수 있도록 Iterator에 저장해 두는 것이 좋습니다.또, 다음의 조작을 실시할 필요는 없습니다.
Streams.stream(Spliterators.spliterator)알 수 없는 크기(반복기, 스플리테이터).주문 완료)
그러자 브라이언 괴츠는 이렇게 대답했다.
샘의 요점은 반복기를 주는 도서관 수업은 많이 있지만 반드시 자신의 분절기를 쓰도록 놔두지 않는다는 것이었다.그래서 할 수 있는 건 call stream(스플리터)밖에 없어요.알 수 없는 크기(반복기).Sam은 이를 위해 Iterator.stream()을 정의할 것을 제안하고 있습니다.
stream() 메서드와 spliterator() 메서드는 라이브러리 라이터/고급 사용자용으로 유지하고 싶습니다.
스플리테이터를 쓰는 것이 반복기보다 쉽기 때문에 반복기 대신 스플리테이터를 쓰는 것이 좋습니다(반복기는 90년대입니다).
하지만 넌 요점을 놓치고 있어.이미 당신에게 반복자를 건네주는 수많은 수업들이 있다.그리고 그들 중 다수는 분쇄기 준비가 되어 있지 않다.
Lambda 메일링 리스트의 이전 설명
이것은 당신이 찾고 있는 답이 아닐 수도 있지만, 프로젝트 람다 메일링 리스트에서 간단히 설명했습니다.아마도 이것은 그 주제에 대한 폭넓은 논의를 촉진하는 데 도움이 될 것이다.
Brian Goetz의 "Streams from Itatable"은 다음과 같이 말합니다.
뒤로 물러서는 중...
스트림을 만드는 방법은 여러 가지가 있습니다.요소를 설명하는 방법에 대한 정보가 많을수록 스트림 라이브러리에서 더 많은 기능과 성능을 얻을 수 있습니다.대부분의 정보에는 다음과 같은 정보가 포함되어 있습니다.
반복기
반복기 + 크기
스플리터
크기를 아는 스플리터
크기를 알고 모든 서브스플릿이 크기를 알고 있다는 것을 더 잘 아는 스플리터.
(Q(요소당 작업량)가 중요하지 않은 경우에는 멍청한 반복기에서라도 병렬화를 추출할 수 있다는 사실에 놀랄 수도 있습니다.)
Itable이 stream() 메서드를 사용하는 경우 크기 정보 없이 반복기를 스플리테이터로 랩합니다.하지만, 대부분의 가능한 것들은 크기 정보를 가지고 있습니다.그 말은 우리가 부족한 물줄기를 공급하고 있다는 거죠.별로 안 좋아요.
여기서 Stephen이 개략적으로 설명한 API 프랙티스의 단점 중 하나는 Collection이 아닌 Itable을 받아들이기 위해 "작은 파이프"를 통해 무언가를 강제하고, 따라서 유용할 경우 크기 정보를 폐기한다는 것입니다.각 데이터를 위한 작업만 수행한다면 문제 없습니다. 하지만 더 많은 작업을 수행할 경우 원하는 모든 정보를 보존할 수 있다면 더 좋습니다.
Itable이 제공하는 디폴트는 정말 형편없는 것입니다.Iterables의 대부분은 그 정보를 알고 있어도 사이즈는 폐기됩니다.
모순?
그러나 이 논의는 Expert Group이 처음에 반복자를 기반으로 한 스트림의 초기 설계에 대해 수행한 변경에 기초하고 있는 것으로 보입니다.
그래도 Collection과 같은 인터페이스에서는 스트림 방식이 다음과 같이 정의되어 있다는 것을 알 수 있습니다.
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
Itable 인터페이스에서 사용되는 것과 동일한 코드일 수 있습니다.
그래서 제가 이 답변이 만족스럽지는 않지만 여전히 논의에 흥미로울 수 있다고 말한 것입니다.
리팩터링의 증거
메일링 리스트의 분석을 계속하면, splitIterator 메서드는 원래 Collection 인터페이스에 있었던 것 같으며, 2013년 어느 시점에서는 Itable로 업그레이드되었습니다.
splitIterator를 Collection에서 Itable로 끌어올립니다.
결론/이론
SplitIterator를 Collection에서 Itable로 업그레이드할 때 스트림 메서드도 함께 이동했어야 했던 것 같기 때문에 Itable에 메서드가 없는 것은 생략된 것일 수 있습니다.
만약 다른 이유들이 있다면 그것들은 분명하지 않다.다른 사람이 다른 이론을 가지고 있나요?
하실 수 .java.util.Collection
는 " " 를 제공합니다.stream()
★★★★
public class Hand extends AbstractCollection<Card> {
private final List<Card> list = new ArrayList<>();
private final int capacity;
//...
@Override
public Iterator<Card> iterator() {
return list.iterator();
}
@Override
public int size() {
return list.size();
}
}
그 후:
new Hand().stream().map(...)
도 같은 요.Iterable
은 매우 될 수 .AbstractCollection
만으로 구현합니다.size()
가 있었다:-) method (다행히 컬렉션의 사이즈가 )
, 「」, 「」를 덮어쓰는 것도 .Spliterator<E> spliterator()
.
언급URL : https://stackoverflow.com/questions/23114015/why-does-iterablet-not-provide-stream-and-parallelstream-methods
'programing' 카테고리의 다른 글
왜 GCC는 정수 나눗셈을 실장할 때 홀수 곱셈을 사용하는가? (0) | 2022.08.07 |
---|---|
vue에서 부모에서 손자에게 소품을 물려주는 방법 (0) | 2022.08.07 |
VueJ에는 React와 같은 제어되지 않은 컴포넌트라는 개념이 있습니까? (0) | 2022.08.07 |
지정된 문자열의 모든 순열 생성 (0) | 2022.08.07 |
파일 설명자에서 파일 포인터를 가져오려면 어떻게 해야 합니까? (0) | 2022.08.07 |