如何从Java集合创建Scala并行集合

如何从Java集合创建Scala并行集合,java,scala,collections,parallel-collections,Java,Scala,Collections,Parallel Collections,。这些隐式def返回包含的Java集合的包装器 Scala 2.9引入了并行集合,其中可以并行执行集合上的操作,并在以后收集结果。这很容易实现,将现有集合转换为并行集合非常简单: myCollection.par 但是在使用JavaConversion从Java集合转换而来的集合上使用“par”有一个问题。如中所述,通过计算所有值并将其添加到新的并行集合中,内在顺序集合被“强制”到新的并行集合中: 其他集合(如列表、队列或流)本质上是 顺序的,即必须一个接一个地访问元素 其他的。这些集合将转换

。这些隐式def返回包含的Java集合的包装器

Scala 2.9引入了并行集合,其中可以并行执行集合上的操作,并在以后收集结果。这很容易实现,将现有集合转换为并行集合非常简单:

myCollection.par
但是在使用JavaConversion从Java集合转换而来的集合上使用“par”有一个问题。如中所述,通过计算所有值并将其添加到新的并行集合中,内在顺序集合被“强制”到新的并行集合中:

其他集合(如列表、队列或流)本质上是 顺序的,即必须一个接一个地访问元素 其他的。这些集合将转换为它们的并行变体 通过将元素复制到类似的并行集合中。对于 例如,函数列表被转换为标准的不可变列表 并行序列,它是一个并行向量

当原始Java集合打算被惰性地评估时,这会导致问题。例如,如果只返回一个Java Iterable,然后将其转换为Scala Iterable,则无法保证Iterable的内容是否会被急切地访问那么,如何从Java集合中创建并行集合,而不必承担评估每个元素的成本呢?我正试图通过使用并行集合并行执行它们来避免这种成本,并希望“获取”提供的前n个结果


据介绍,有一系列的收集类型花费固定的时间,但似乎没有办法保证这些类型可以通过JavaConversion创建(例如,可以创建“Set”,但是“HashSet”?)。

Parallel需要随机访问,而java.lang.Iterable不提供。这是一个根本性的不匹配,任何数量的转换都不会让你轻松通过

用一个非编程的类比,你不能通过同时将一个人从新加坡送到英国和另一个人从澳大利亚送到新加坡来将一个人从澳大利亚送到英国

或者在编程中,如果您正在处理一个实时数据流,那么您无法通过在不增加延迟的情况下同时处理来自现在的数据和来自五分钟前的数据来并行处理它


您需要至少提供一些随机访问的东西,比如java.util.List.listIterator(Int),而不是Iterable,通过
JavaConversion
s从Java集合中获得的每个集合在默认情况下都不是可并行化的Scala集合-这意味着它将始终被重新评估为其相应的并行集合实现。这是因为并行执行至少依赖于以下概念:它必须可拆分为更小的子集,不同的处理器可以处理这些子集

我不知道您的Java集合在数据结构的意义上是什么样子的,但是如果它是一个树状的东西,或者是一个数组,其下面的元素被惰性地计算,那么很可能您可以轻松地实现一个
拆分器

如果您不想迫不及待地
强制
实现Java集合API的惰性集合,那么您唯一的选择就是为该特定的惰性Java集合执行。在这个新的实现中,您必须提供拆分迭代器的方法(即,
拆分器

一旦你实现了这个新的并行集合,它知道如何分割你的数据结构,你就应该为你的特定Java集合创建一个定制的Scala包装器(在这一点上,它只是一个额外的样板,看看它是如何在
JavaConversions
中完成的)并覆盖其
par
以返回特定的并行集合

对于索引序列,您甚至可以一般地这样做。假设您的Java集合是一个序列(在Java中是a),具有一个特别有效的
get
方法,那么您可以将
Splitter
实现为一个迭代器,在
0
size-1
的初始范围内调用
get
,并通过细分此范围进行拆分


如果您这样做,那么标准库的修补程序总是受欢迎的。

我想我假设每次检索下一个元素的调用(即Iterable.iterator().next())都是在线程内运行的。请注意,最好使用JavaConverts,而不是JavaConverts,有了这个,你就可以做一些类似的事情。