2016-09-02 4 views
2

Collectors.toMap()에 의해 생성 된 항목 수를 병합 기능으로 제한하는 방법을 찾고 있습니다. 다음 예를 살펴 보겠습니다 : 위의와Collectors.toMap() 항목을 제한 할 수 있습니까?

Map<String, Integer> m = Stream.of("a", "a", "b", "c", "d") 
    .limit(3) 
    .collect(toMap(Function.identity(), s -> 1, Integer::sum)); 

문제는 난 단지 결과지도 (a=2, b=1)의 두 요소를해야한다는 것입니다. 처리 된 스트림을 단락시킬 수있는 편리한 방법이 있습니까? 키가 있습니까?

+0

필터링 할 수 없습니까? – SamTebbs33

+0

이렇게 할 수 있니? 허용되는지 확실하지 않습니다. Map m = Stream.of ("a", "a", "b", "c", "d") .limit (m.size() <3? Integer.MAX_VALUE : 3) . 콜렉터 (toMap (Function.identity(), 1, Integer :: sum)); – nbokmans

+3

* "방법이 있습니까?"* 네 자신의'toMap()'콜렉터를 작성하십시오. 그거 편리할까요? 원근법의 물질, 나는 짐작한다. – Andreas

답변

2

가능한 해결 방법은 Stream의 스플 리터 레이터를 래핑하는 Spliterator을 직접 작성하는 것입니다. 이 Spliterator은 줄 바꿈 된 spliterator로 전진하는 호출을 위임하고 많은 별개 요소의 계산 논리를 포함합니다.

이렇게하려면 서브 클래스 AbstractSpliterator을 사용하고 우리 자신의 tryAdvance 논리를 제공 할 수 있습니다. 다음에서, 모든 요소는 세트에 추가됩니다. 해당 세트의 크기가 최대 값보다 커지거나 래핑 된 spliterator에 남아있는 요소가없는 경우을 반환하여 고려해야 할 요소가 없음을 나타냅니다. 별개의 요소에 도달하면이 작업이 중단됩니다.

Map<String, Long> m = 
    distinctLimit(Stream.of("a", "a", "b", "c", "d"), 3) 
     .collect(Collectors.groupingBy(Function.identity(), Collectors.counting())); 

및 출력은 즉 3 개별의 키와지도, {a=2, b=1, c=1}을 예상 할 수 :

귀하의 예제 코드와
private static <T> Stream<T> distinctLimit(Stream<T> stream, int max) { 
    Spliterator<T> spltr = stream.spliterator(); 
    Spliterator<T> res = new AbstractSpliterator<T>(spltr.estimateSize(), spltr.characteristics()) { 

     private Set<T> distincts = new HashSet<>(); 
     private boolean stillGoing = true; 

     @Override 
     public boolean tryAdvance(Consumer<? super T> action) { 
      boolean hasRemaining = spltr.tryAdvance(elem -> { 
       distincts.add(elem); 
       if (distincts.size() > max) { 
        stillGoing = false; 
       } else { 
        action.accept(elem); 
       } 
      }); 
      return hasRemaining && stillGoing; 
     } 
    }; 
    return StreamSupport.stream(res, stream.isParallel()).onClose(stream::close); 
} 

, 당신은 할 것이다.

+0

'Iterator'를 사용하는 것이 더 깨끗해 보입니다. – shmosel