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

Dan*_*ell 5 java collections scala parallel-collections

将Java Collection转换为Scala等效项的最简单方法是使用JavaConversions,因为Scala 2.8..这些隐式defs返回包含的Java Collection的包装器.

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

myCollection.par
Run Code Online (Sandbox Code Playgroud)

但是使用JavaConversions从Java集合转换的集合上使用'par'会有问题.如并行收集转换中所述,通过评估所有值并将它们添加到新的并行集合,本质上将顺序集合"强制"为新的并行集合:

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

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

根据Parallel Collection Conversions,有一系列的收集类型需要花费不变的时间,但似乎没有办法确保JavaConversions可以创建这些类型(例如,'Set'可以创建,但是那个'HashSet'?).

axe*_*l22 4

首先,通过JavaConversions 从 Java 集合中获取的每个集合默认情况下都不是可并行化的 Scala 集合 - 这意味着它将始终被重新评估为其相应的并行集合实现。其原因是并行执行至少依赖于Splitters的概念 - 它必须可拆分为较小的子集,然后不同的处理器可以处理这些子集。

我不知道你的 Java 集合在数据结构意义上看起来如何,但如果它是一个类似树的东西或者是一个其元素被延迟计算的数组,那么你很可能可以轻松地实现一个Splitter.

如果您不想急切地force使用实现 Java 集合 API 的惰性集合,那么您唯一的选择是为该特定惰性 Java 集合实现新类型的并行集合。在这个新的实现中,您必须提供拆分迭代器(即 a Splitter)的方法。

一旦你实现了这个知道如何分割数据结构的新并行集合,你应该为你的特定 Java 集合创建一个自定义的 Scala 包装器(此时它只是一点额外的样板,看看它是如何完成的JavaConversions)并重写它par返回您的特定并行集合。

您甚至可以对索引序列进行一般性的操作。鉴于您的 Java 集合是一个List具有特别高效方法的序列(在 Java 中为 a )get,您可以将 实现Splitter为迭代器,该迭代器get在初始范围 from0到内​​调用size - 1,并通过细分该范围来分割。

如果您这样做,我们总是欢迎对标准库进行补丁。