互操作性:在 Java 和 Scala 之间共享对象或行的数据集,有两种方式。我将 Scala 数据集操作放在 Java 个中间

Interoperability : sharing Datasets of objects or Row between Java and Scala, two ways. I put a Scala dataset operation in the middle of Java ones

目前,我的主要应用程序是使用 Java Spring-boot 构建的,这不会因为方便所以改。
@Autowired 服务bean 实现,例如:

许多用户案例函数都是这种调用:

What are associations(year=2020) ?

我的申请转发给 datasetAssociation(2020),它与企业和机构数据集以及城市和地方当局一起运作,以提供有用的结果。

许多人推荐我受益于 Scala 能力

为此,我正在考虑涉及数据集之间其他操作的操作:

我有这个操作要做,就数据集而言 reached/involved :
协会.enterprises.establishments.cities.localautorities

我可以在 Scala 中写粗体部分吗?这意味着:

  1. Java构建的Dataset<Row>代码被发送到Scala函数待完成。

  2. Scala 创建一个包含 EnterpriseEstablishment 个对象的新数据集。
    a) 如果对象的源是用 Scala 编写的,我不必在 中为它重新创建一个新源Java.
    b) 相反,如果对象的源代码写在 Java,我不必在 Scala.
    c) 我可以使用 Scala 对象 return Java边直接.

  3. Scala 将不得不调用在 Java 中实现的函数并将它们发送给底层数据集它正在创建(例如用城市信息完成它们)。

Java 随时调用 Scala 方法
Scala 也随时调用 Java 方法:

一个操作可以跟随一个
Java -> Scala -> Scala -> Java -> Scala -> Java -> Java
路径(如果需要),以调用方法的本地语言表示。
因为我事先并不知道哪些部分对移植到 Scala 有用。

完成这三点,我会认为 JavaScala 可以双向互操作并受益从另一个。

但我可以实现这个目标吗(在 Spark 2.4.x 或更可能在 Spark 3.0.0 中)?

总结一下,Java 和 Scala 是否可以互操作这两种方式,一种方式:

是的,没有性能下降或过于笨拙的额外代码是可能的。 Scala 和 Java 几乎可以完美互操作,而且 Spark Dataset API 在 Java 和 Scala 之间共享。无论您使用 Java 还是 Scala,Dataset class 都完全相同。正如您在 javadoc or scaladoc 中看到的(注意它们仅在布局上不同,在内容上没有区别)Java 和 Scala 代码是完全可以互换的。顶多Scala的代码会简洁一点。

正如 Jasper-M 所写,scala 和 java 代码是完美的 inter-operable:

  • 它们都编译成 .class 文件,由 jvm
  • 以相同的方式执行
  • spark java 和 scala API 一起工作,有几个细节:
    • 两者使用相同的数据集class,所以没有问题
    • 然而,SparkContext 和 RDD(以及所有 RDD 变体)具有在 java 中不实用的 scala api。主要是因为 scala 方法将 scala 类型作为输入,而不是您在 java 中使用的类型。但是它们都有 java 包装器(JavaSparkContext,JavaRDD)。在 java 中编码,您可能已经看过那些包装器了。

现在,正如很多人所推荐的那样,spark首先是一个scala库,scala语言比java(*)更强大,用scala写spark代码会容易很多。此外,您会在 scala 中找到更多 code-example。通常很难找到 java 复杂数据集操作的代码示例。

所以,我认为您应该注意的两个主要问题是:

  1. (与 spark 无关,但有必要)有一个编译这两种语言并允许 two-way inter-operability 的项目。我认为 sbt 提供了它 out-of-the-box,对于 maven,您需要使用 scala 插件并且(根据我的经验)将 java 和 scala 文件都放在 java 文件夹中。否则一个可以调用另一个,但不能相反(scala 调用 java 但 java 不能调用 scala,反之亦然)
  2. 您应该注意每次创建类型化数据集时使用的编码器(即 Dataset[YourClass] 而不是 Dataset<Row>)。在 Java 中,对于 java 模型 classes,您需要明确地使用 Encoders.bean(YourClass.class)。但在 scala 中,默认情况下 spark 会隐式找到编码器,并且编码器是为 scala case classes(“产品类型”)和 scala 标准集合构建的。所以请注意使用了哪些编码器。例如,如果您在 Scala 中创建一个 YourJavaClass 的数据集,我认为您可能必须明确给出 Encoders.bean(YourJavaClass.class) 才能使其正常工作并且没有序列化问题。

最后一点:您写道您使用 java Spring-boot。所以

  • 请注意,Spring 设计完全违背了 scala/functional 推荐的做法。到处使用 null 和可变的东西。你仍然可以使用 Spring,但在 scala 中可能会很奇怪,社区可能不会轻易接受它。
  • 您可以从 spring 上下文调用 spark 代码,但不应使用来自 spark 的 spring(上下文),尤其是在 spark 分发的方法内部,例如 rdd.map。这将尝试在每个工作人员中创建 Spring 上下文,这非常慢并且很容易失败。

(*) 关于“scala 比 java 更强大”:我并不是说 scala 比 java 好(我确实这么认为,但这是一个问题品尝 :)。我的意思是 scala 语言比 java 提供了更多的表现力。基本上它用更少的代码做更多的事情。主要区别是:

  • implicits,被 spark 大量使用api
  • 单子 + for-comprehension
  • 当然还有强大的type-system(例如阅读co-variant类型,List[Dog]是scala中List[Animal]的子class,但不是在 java)