spliterators parallelism java lambda java-8 spliterator

spliterators - java parallelism



Comprender Spliterator, Collector y Stream en Java 8 (4)

Como principiante, familiarícese con la programación funcional en google guava donde se usan Iteradores tradicionales. Examine cómo se filtran, transforman y recogen los objetos. Luego muévete a java 8.

Tengo problemas para entender la interfaz de Stream en Java 8, especialmente cuando tiene que ver con las interfaces de Spliterator y Collector . Mi problema es que simplemente no puedo entender aún las Spliterator y Collector , y como resultado, la interfaz de Stream todavía es algo oscura para mí.

¿Qué es exactamente un Spliterator y un Collector , y cómo puedo usarlos? Si estoy dispuesto a escribir mi propio Spliterator o Collector (y probablemente mi propio Stream en ese proceso), ¿qué debo hacer y qué no hacer?

Leí algunos ejemplos dispersos por la web, pero como todo aquí es aún nuevo y está sujeto a cambios, los ejemplos y tutoriales son todavía muy escasos.


Es casi seguro que nunca tendrá que tratar con Spliterator como usuario; solo debería ser necesario si está escribiendo tipos de Collection usted mismo y también tiene la intención de optimizar las operaciones paralelizadas en ellos.

Para lo que vale, un Spliterator es una forma de operar sobre los elementos de una colección de manera que es fácil separar parte de la colección, por ejemplo, porque estás paralelizando y quieres que un hilo funcione en una parte de la colección. , un hilo para trabajar en otra parte, etc.

En esencia, nunca debería guardar valores de tipo Stream en una variable. Stream es como un Iterator , ya que es un objeto de uso único que casi siempre usarás en una cadena fluida, como en el ejemplo de Javadoc:

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

Collector es la versión abstracta más generalizada posible de una operación "reducir" a la map / reduce; en particular, necesita soportar pasos de paralelización y finalización. Los ejemplos de Collector s incluyen:

  • sumando, por ejemplo, Collectors.reducing(0, (x, y) -> x + y)
  • StringBuilder anexa, por ejemplo, Collector.of(StringBuilder::new, StringBuilder::append, StringBuilder::append, StringBuilder::toString)

Los siguientes son ejemplos del uso de colectores predefinidos para realizar tareas de reducción mutables comunes:

// 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 básicamente significa "Iterator divisible".

Un solo hilo puede atravesar / procesar todo el Spliterator, pero el Spliterator también tiene un método trySplit() que "dividirá" una sección para que otra persona (típicamente, otro hilo) la procese, lo que deja al spliterator actual con menos trabajo.

Collector combina la especificación de una función de reduce (de fama de reducción de mapa), con un valor inicial y un valor para combinar dos resultados (lo que permite combinar resultados de flujos de trabajo divididos).

Por ejemplo, el Recopilador más básico tendría un vaue inicial de 0, agregaría un entero a un resultado existente y ''combinaría'' dos resultados agregándolos. De esta forma, se suma un flujo de enteros dividido en dos partes.

Ver: