[java] Java 8의 분할기, 수집기 및 스트림 이해

StreamJava 8 의 인터페이스, 특히 Spliteratorand Collector인터페이스 와 관련된 인터페이스를 이해하는 데 문제 가 있습니다. 내 문제는 내가 간단하게 이해할 수 있다는 것입니다 SpliteratorCollector인터페이스를 아직 그 결과, Stream인터페이스는 여전히 다소 나에게 모호하게됩니다.

정확히 a Spliterator와 a 는 무엇 Collector이며 어떻게 사용합니까? 내가 직접 ( Spliterator또는 Collector아마도 Stream그 과정에서 내 자신 을) 기꺼이 쓰려면 어떻게해야합니까?

나는 웹에 흩어져있는 몇 가지 예를 읽었지만 여기의 모든 것이 여전히 새롭고 변경 될 수 있으므로 예제와 자습서는 여전히 매우 드 r니다.



답변

거의 확실하게 Spliterator사용자 를 다루지 않아도됩니다 . 당신이있는 거 쓰는 경우에만 필요합니다 Collection종류의 자신을하고 또한 최적화하려는 그들에 대한 작업을 병렬화.

가치있는 Spliterator것은 a는 컬렉션의 일부를 쉽게 분리 할 수있는 방법으로 컬렉션의 요소를 조작하는 방법입니다. 하나의 스레드가 다른 부분에서 작동하는 등

본질적으로 유형의 값을 Stream변수에 저장해서는 안됩니다 . Javadoc 예제에서와 같이 거의 항상 유동 체인에서 사용할 일회용 객체이기 때문에 Stream일종의입니다 Iterator.

int sum = widgets.stream()
                  .filter(w -> w.getColor() == RED)
                  .mapToInt(w -> w.getWeight())
                  .sum();

Collector“축소”연산의 가장 일반적이고 추상적 인 버전은 la map / reduce입니다. 특히, 병렬화 및 마무리 단계를 지원해야합니다. 의 예는 Collector다음과 같습니다.

  • 합산, 예. Collectors.reducing(0, (x, y) -> x + y)
  • StringBuilder 추가, 예 : Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString)

답변

Spliterator 기본적으로 “분할 가능한 반복자”를 의미합니다.

단일 스레드는 전체 Spliterator 자체를 통과 / 처리 할 수 ​​있지만 Spliterator에는 trySplit()다른 사람 (일반적으로 다른 스레드)이 처리 할 섹션을 “분할” 하는 방법 이있어 현재의 Spliterator가 적은 작업으로 남겨집니다.

Collectorreduce함수 (map-reduce 명성) 의 사양 과 초기 값을 결합하고 두 결과를 결합하는 함수 (따라서 분할 된 작업 스트림의 결과를 결합 할 수 있도록 함)를 결합합니다.

예를 들어, 가장 기본적인 수집기는 초기 값이 0이고 기존 결과에 정수를 추가 한 다음 두 결과를 더하여 ‘결합’합니다. 따라서 분할 된 정수 스트림을 합산하십시오.

보다:


답변

다음은 사전 정의 된 콜렉터를 사용하여 일반적인 변경 가능한 축소 작업을 수행하는 예입니다.

 // Accumulate names into a List
 List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());

 // Accumulate names into a TreeSet
 Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));

 // Convert elements to strings and concatenate them, separated by commas
 String joined = things.stream()
                       .map(Object::toString)
                       .collect(Collectors.joining(", "));

 // Compute sum of salaries of employee
 int total = employees.stream()
                      .collect(Collectors.summingInt(Employee::getSalary)));

 // Group employees by department
 Map<Department, List<Employee>> byDept
     = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment));

 // Compute sum of salaries by department
 Map<Department, Integer> totalByDept
     = employees.stream()
                .collect(Collectors.groupingBy(Employee::getDepartment,
                                               Collectors.summingInt(Employee::getSalary)));

 // Partition students into passing and failing
 Map<Boolean, List<Student>> passingFailing =
     students.stream()
             .collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));


답변

인터페이스 Spliterator스트림 의 핵심 기능입니다 .

stream()parallelStream()기본 방법이 제시되어 Collection인터페이스를 제공합니다. 이 메소드는 다음에 대한 호출을 통해 Spliterator를 사용합니다 spliterator().

...

default Stream<E> stream() {
    return StreamSupport.stream(spliterator(), false);
}

default Stream<E> parallelStream() {
    return StreamSupport.stream(spliterator(), true);
}

...

Spliterator는 스트림을 작은 부분으로 나누는 내부 반복기입니다. 이러한 작은 부품은 병렬로 처리 할 수 ​​있습니다.

다른 방법 중에서 Spliterator를 이해하는 데 가장 중요한 두 가지가 있습니다.

  • boolean tryAdvance(Consumer<? super T> action)
    와 달리 Iterator다음 요소로 작업을 수행하려고합니다. 작업이 성공적으로 실행되면이 메서드는를 반환합니다 true. 그렇지 않으면, 리턴 false합니다. 즉, 요소가 없거나 스트림 끝이 있음을 의미합니다.

  • Spliterator<T> trySplit()
    이 방법을 사용하면 데이터 세트를 하나 이상의 기준 (파일 크기, 행 수 등)에 따라 여러 개의 작은 세트로 분할 할 수 있습니다.


답변