2012-10-12 79 views
5

The easiest way to convert a Java Collection to a Scala equivalent is using JavaConversions, since Scala 2.8.. Estas envolturas de retorno defs implícitas para la colección contenida de Java.Cómo crear una colección paralela de Scala a partir de una colección de Java

Scala 2.9 introdujo colecciones paralelas, donde las operaciones en una colección se pueden ejecutar en paralelo y el resultado se recoge más tarde. Esto es fácil de implementar, la conversión de una colección existente en uno paralelo es tan simple como:

myCollection.par 

Pero hay un problema con el uso de 'par' en colecciones convertidos a partir de colecciones de Java utilizando JavaConversions. Como se describe en Parallel Collection Conversions, inherentemente colecciones secuenciales se 'forzado' en una nueva colección paralelo mediante la evaluación de todos los valores y la adición de ellos a la nueva colección paralelo:

Otras colecciones, tales como listas, colas o arroyos, son inherentemente secuencial en el sentido de que se debe acceder a los elementos uno después de el otro. Estas colecciones se convierten a sus variantes paralelas copiando los elementos en una colección paralela similar. Para el ejemplo , una lista funcional se convierte en una secuencia paralela estándar inmutable , que es un vector paralelo.

Esto causa problemas cuando se pretende evaluar holgadamente la colección original de Java. Por ejemplo, si solo se devuelve un Iterable de Java, luego convertido a un Iterable de Scala, no hay garantía de que el contenido de Iterable esté destinado a ser accedido con entusiasmo o no. Entonces, ¿cómo debería crearse una colección paralela a partir de una colección Java sin sostener el costo de evaluar cada elemento? Este es el costo que trato de evitar al usar una colección paralela para ejecutarlos en paralelo y con suerte 'tomar' los primeros n resultados que se ofrecen.

De acuerdo con Parallel Collection Conversions hay una serie de tipos de colección que cuestan tiempo constante, pero no parece haber una manera de obtener una garantía de que JavaConversions pueda crear estos tipos (p. Ej., Se puede crear 'Set', pero es eso un 'HashSet'?).

+1

Tenga en cuenta que sería una mejor idea usar JavaConverters en lugar de JavaConversions como este último, con eso allí sería capaz de hacer algo como .asScala.toList.par. –

Respuesta

4

En primer lugar, cada colección obtenida a través de JavaConversion s de una colección Java no es una colección Scala por paralela predeterminada, esto significa que siempre se volverá a evaluar en su correspondiente implementación de colección paralela. La razón de esto es que la ejecución en paralelo se basa en los conceptos de Splitters al menos, tiene que ser divisible en subconjuntos más pequeños en los que diferentes procesadores pueden trabajar.

No sé cómo se ve tu colección Java en el sentido de estructura de datos, pero si se trata de un árbol o una matriz debajo de cuyos elementos se evalúan perezosamente, es probable que puedas implementar fácilmente un Splitter.

Si no desea ansiosamente force una colección diferida que implementa una API de recopilación de Java, entonces su única opción es implement a new type of a parallel collection para esa colección Java lazy en particular. En esta nueva implementación, debe proporcionar los medios para dividir el iterador (es decir, un Splitter).

Una vez que implementa esta nueva colección paralela que sabe cómo dividir su estructura de datos, debe crear un envoltorio Scala personalizado para su colección Java específica (en este punto es solo un poco repetitivo, vea cómo se hace) en JavaConversions) y anula su par para devolver su colección paralela específica.

Incluso podría hacer esto genéricamente para secuencias indexadas. Dado que su colección Java es una secuencia (en Java, a List) con un método particularmente eficiente get, puede implementar Splitter como un iterador que llama al get dentro del rango inicial de 0 a size - 1, y se divide subdividiendo este rango.

Si lo hace, los parches para la biblioteca estándar siempre son bienvenidos.

1

Paralelo requiere acceso aleatorio y java.lang.Iterable no lo proporciona. Esta es una falta de coincidencia fundamental que ninguna cantidad de conversiones le hará pasar cómodamente.

Para utilizar una analogía que no sea de programación, no se puede obtener una persona de Australia a Inglaterra enviando a una persona de Singapur a Inglaterra y otra de Australia a Singapur al mismo tiempo.

O en la programación, si está procesando una transmisión en vivo de datos no puede paralelizar procesando los datos a partir de ahora al mismo tiempo que los datos de hace cinco minutos sin agregar latencia.

Necesitará algo que proporcione al menos algo de acceso aleatorio, como java.util.List.listIterator (Int) en lugar de Iterable.

+0

Supongo que asumí que cada llamada para recuperar el siguiente elemento (es decir, Iterable.iterator(). Next()) se ejecutó dentro de un hilo. –

Cuestiones relacionadas