【问题标题】:How to create a Scala parallel collection from a Java collection如何从 Java 集合创建 Scala 并行集合
【发布时间】:2012-10-03 06:45:56
【问题描述】:

The easiest way to convert a Java Collection to a Scala equivalent is using JavaConversions, since Scala 2.8.。这些隐式定义返回包含的 Java 集合的包装器。

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

myCollection.par

但是在使用 JavaConversions 从 Java 集合转换而来的集合上使用“par”会出现问题。如Parallel Collection Conversions 中所述,通过评估所有值并将它们添加到新的并行集合中,固有的顺序集合被“强制”到新的并行集合中:

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

当原始 Java 集合打算被延迟评估时,这会导致问题。例如,如果只返回一个 Java Iterable,然后转换为 Scala Iterable,则不能保证 Iterable 的内容是否会被急切地访问。 那么应该如何从 Java 集合创建并行集合,而不需要维持评估每个元素的成本? 我试图通过使用并行集合来并行执行它们来避免这种成本,并希望'获取提供的前 n 个结果。

根据Parallel Collection Conversions,有一系列的集合类型会花费恒定的时间,但似乎没有办法保证这些类型可以由 JavaConversions 创建(例如,可以创建“Set” ,但那是一个'HashSet'吗?)。

【问题讨论】:

  • 请注意,最好使用 JavaConverters 而不是 JavaConversions 作为后者,这样您就可以执行类似 .asScala.toList.par 之类的操作。

标签: java scala collections parallel-collections


【解决方案1】:

首先,通过JavaConversions 从 Java 集合中获得的每个集合都不是默认可并行化的 Scala 集合——这意味着它总是会被重新评估为相应的并行集合实现。这样做的原因是并行执行至少依赖于Splitters 的概念——它必须被分成更小的子集,然后不同的处理器可以处理。

我不知道你的 Java 集合在数据结构的意义上是怎样的,但如果它是一个树状的东西或一个数组,其元素被延迟评估,你很可能可以轻松地实现 Splitter。

如果您不想急切地 force 实现 Java 集合 API 的惰性集合,那么您唯一的选择是 implement a new type of a parallel collection 用于特定的惰性 Java 集合。在这个新实现中,您必须提供拆分迭代器的方法(即Splitter)。

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

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

如果您这样做了,我们随时欢迎为标准库提供补丁。

【讨论】:

    【解决方案2】:

    Parallel 需要随机访问,而 java.lang.Iterable 不提供。这是根本的不匹配,没有多少转化可以让您轻松通过。

    使用非编程类比,您不能通过同时将一个人从新加坡派往英国和另一个人从澳大利亚派往新加坡来将一个人从澳大利亚带到英国。

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

    您需要至少提供一些随机访问的东西,例如 java.util.List.listIterator(Int) 而不是 Iterable。

    【讨论】:

    • 我猜我假设每次调用检索下一个元素(即 Iterable.iterator().next())都是在线程内运行的。
    猜你喜欢
    • 1970-01-01
    • 2015-10-09
    • 2010-11-18
    • 2020-07-03
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 2020-03-25
    相关资源
    最近更新 更多