1

Java 8 스트림을 사용하면 임의의 제약 조건으로 그룹화하면서 요소를 수집 할 수 있습니다. 예를 들어 :스트림의 Java 그룹화

Map<Type, List<MyThing>> grouped = stream 
    .collect(groupingBy(myThing -> myThing.type())); 

그러나이 스트림이 완전히 통해 읽을 수 있어야한다는 단점이있다, 그래서 grouped에 향후 작업의 게으른 평가의 기회가 없다.

Stream<Tuple<Type, Stream<MyThing>>>과 같은 항목을 얻기 위해 그룹화 작업을 수행 할 수있는 방법이 있습니까? 전체 데이터 세트를 평가하지 않고도 모든 언어로 지연 그룹화하는 것이 개념적으로 가능합니까?

+1

아니요, 이것은 실제로 이해가되지 않습니다. 포기해라. –

답변

4

게으른 그룹화 개념은 실제로 의미가 없습니다. 그룹화는 정의에 따라 각 키의 모든 요소를 ​​검색하는 오버 헤드를 피하기 위해 그룹을 미리 선택하는 것을 의미합니다. "게으른 그룹"과 같을 것이다 :

List<MyThing> get(Type key) { 
    source.stream() 
      .filter(myThing -> myThing.type().equals(key)) 
      .collect(toList()); 
} 

을 당신은 당신이 그것을 필요로하거나 그룹화 맵 캐싱의 메모리 오버 헤드를 피하기 위해 원하는 경우,이 완벽하게 잘 알고 때 반복을 연기하는 것을 선호합니다. 그러나 미리 반복하지 않고 선택 프로세스를 최적화 할 수는 없습니다.

+0

제 생각에 그룹화 키의 수가 엄청나게 크지 않고 그룹화 값이 스트림이기 때문에 그룹화 맵의 오버 헤드가 그렇게 나쁘지는 않을 것입니다. – kag0

+3

@ kag0 물론 키에 대한 맵을 스트림에 만들 수 있지만 스트림이 소스 컬렉션을 가리키고있어 성능 향상을 거의 가져 오지 못하거나 스트림이 그룹화 된 컬렉션을 가리키고 있습니다 (예 :'groupingBy (MyThing :: type, collectingAndThen (toList(), List :: stream()))')하지만 메모리를 절약 할 수 있습니다. – shmosel

+2

@ kag0 부수적으로 데이터의 얕은 복사본 만 생성하기 때문에 그룹화에 메모리 오버 헤드가 많지 않습니다. 아마도'n * 4' 바이트보다 약간 비싸지 만,'n'은 소스 콜렉션의 크기입니다. – shmosel

0

나는이 다른 파티션에 사용되는 메모리의 임의의 큰 양을 생산할 수있는 게으른 스트림 Stream<Tuple<Type, Stream<MyThing>>>의 하나 개의 파티션 스트림 (Tuple<Type, Stream<MyThing>>)에서 읽기 때문에 이해한다고 생각하지 않습니다.

예. 자연의 순서로 양의 정수의 게으른 스트림을 고려하고 가장 작은 소수 요소로 그룹화하십시오. 그런 다음 파티션의 스트림에서 마지막으로 수신 된 요소를 읽으면 이전에받은 스트림에서 점점 더 많은 정수가 생성됩니다.

+0

이것은 사실이지만 예상치 못한 것은 아니라고 생각합니다. 'collect (groupingBy()) '를 사용하여 그 연산을 시도하면 같은 결과를 낳을 것입니다 (메모리 박탈로 인해 결코 완료되지 않습니다). 무한 스트림에 대한 작업을 수행하려면 무한한 양의 메모리 또는 시간이 필요합니다. – kag0

1

스트림은 중간 또는 터미널 스트림 작업을 호출 할 때 한 번만 작동해야합니다. 예를 들어, 같은 소스가 두 개 이상의 파이프 라인을 제공하는 "분기 된"스트림이나 동일한 스트림의 여러 탐색을 배제합니다.

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html

그래서 내가 그것을 소비하는 새로운 스트림을 생성하지 않고 그것을 분할하는 방법이 없다고 생각 :

은의 문서에서 가져옵니다.

+0

이것은 내 질문을 진술하는 또 다른 방법입니다. 'Stream.collect'는 터미널 조작이며'Collectors.groupingBy'를 사용하는 유일한 방법입니다. 스트림에 그룹화 할 터미널이 아닌 방법이 있는지 알고 싶습니다. – kag0

0

개념적으로 전체 데이터 집합을 평가하지 않고 언어를 그룹화하는 것이 가능합니까?

아니요, 전체 데이터 세트를 확인하거나 데이터의 악용 가능한 패턴을 보장하지 않으면 전체 데이터 세트를 올바르게 그룹화 할 수 없습니다. 예를 들어 처음 10,000 개의 정수를 느리게 짝수로 그룹화 할 수 있지만 임의로 10,000 개의 정수를 짝수로 그룹화 할 수는 없습니다.

비단식 방식으로 그룹화하는 것 ... 좋은 생각 인 것처럼 보이지는 않습니다. 개념적으로 스트림의 그룹화 함수는 여러 스트림을 분기하는 것처럼 여러 스트림을 반환해야하며 Java 8에서는이를 지원하지 않습니다.

네이티브 스트림 메서드를 사용하여 비단 말로 그룹화하려는 경우 정렬 된 메서드를 악용 할 수 있습니다. 그룹을 다르게 처리하지만 그룹 내의 모든 요소를 ​​동일하게 취급하는 분류기를 지정하면 group1, group2, group3 등으로 끝납니다.이것은 당신에게 게으른 평가를하지는 않지만 그룹핑입니다.

+0

나는 이상한 예를 따를지는 모르겠다. 왜 그런지 설명해 주시겠습니까? – kag0

+0

100,000 개의 정확도로 값을 예측할 수 있기 때문에 첫 번째 10,000 개의 정수를 느리게 그룹화하여 확률과 확률로 그룹화 할 수 있습니다. 짝수 또는 홀수 여부에 따라 순차적 인 정수 집합을 지연 그룹으로 묶을 수 있습니다. 이는 even-odd가 예측 가능한 패턴이기 때문입니다. 그러나 10,000 개의 임의의 정수 만 있으면 데이터를 예측할 수있는 능력을 잃어 버리기 때문에 그룹을 올바르게 그룹화하려면 모든 데이터를 검사해야합니다. – Jeutnarg

관련 문제