将Java List转换为Scala Seq

46

我需要在Java中实现一个返回Scala Seq的方法。

但是我遇到了以下错误:

java.util.ArrayList cannot be cast to scala.collection.Seq

这是我目前的代码:

@Override
public Seq<String> columnNames() {
    List<String> a = new ArrayList<String>();
    a.add("john");
    a.add("mary");
    Seq<String> b = (scala.collection.Seq<String>) a;
    return b;
}

但是scala.collection.JavaConverters似乎没有提供将其转换为Seq的可能性。


1
如果你试图在Java中对Scala集合进行任何操作,那么你会自找麻烦。编写一些Scala代码,使用scala.collection.JavaConverters进行转换。 - Luigi Plinge
@TzachZohar 大多数答案都是用 Scala 完成的。我的代码是 Java,它是一个庞大的程序的一部分,我无法将这个处理外部化... - Fundhor
正如@LuigiPlinge所提到的,这不是一个好主意!你可能会在尝试在此序列上调用方法时遇到很多问题,更不用说尝试调用任何需要隐式参数的方法了。 - Mateusz Dymczyk
在文档中,“它们可能导致意外的行为和性能问题”听起来不是很令人信服...特别是因为接下来的句子建议使用“JavaConverters”,它们提供“相同”的转换。 :) - Dima
7个回答

53

JavaConverters是我解决这个问题所需要的。

import scala.collection.JavaConverters;

public Seq<String> convertListToSeq(List<String> inputList) {
    return JavaConverters.asScalaIteratorConverter(inputList.iterator()).asScala().toSeq();
}

2
较短的版本:JavaConverters.asScalaIterableConverter(a).asScala().toSeq(); - Adrien Brunelat
JavaConverters.collectionAsScalaIterableConverter(list).asScala().toSeq() 是我在 Scala 2.12.6 中采用的正确方法。如果源是可迭代对象而不是集合,则还有一个 JavaConverters.iterableAsScalaIterableConverter 方法。 - Per Lundberg
asScalaIteratorConverter (java.util.Iterator<A>)在JavaConverters中无法应用于(scala.collection.Iterator<java.lang.String>)的原因是:不存在类型变量A的实例,使得Iterator<String>符合Iterator<A>。 - sapy

24

JavaConversions 应该可行。我认为,你正在寻找像这样的东西:JavaConversions.asScalaBuffer(a).toSeq()


6
JavaConversions is deprecated and now it should be written as JavaConverters.asScalaBuffer(a) - kap
应该这样做吗?不,更像是由某个未知的人推荐的更好的想法 :) - Dima
1
可能吧。我只是按照Scala API中的提示进行操作。我不认识任何编写或弃用它的人;-) - kap

17
从Scala 2.13开始,scala.jdk.javaapi.CollectionConverters包替换了已废弃的包scala.collection.JavaConverters/JavaConversions
import scala.jdk.javaapi.CollectionConverters;

// List<String> javaList = Arrays.asList("a", "b");
CollectionConverters.asScala(javaList).toSeq();
// Seq[String] = List(a, b)

6

这对我有用!(Java 8,Spark 2.0.0)

import java.util.ArrayList;

import scala.collection.JavaConverters;
import scala.collection.Seq;

public class Java2Scala
{

    public Seq<String> getSeqString(ArrayList<String> list)
        {
            return JavaConverters.asScalaIterableConverter(list).asScala().toSeq();
        }

}

5
尊敬的Fundhor,在我的IDE中找不到asScalaIterableConverter方法。可能是因为Scala版本的差异。我使用的是Scala 2.11。相反,asScalaIteratorConverter方法被找到了。我稍微修改了你的代码片段,并成功运行。

请参考如下代码:scala.collection.JavaConverters.asScalaIteratorConverter(columnNames.iterator()).asScala().toSeq(),其中columnNames是一个java.util.List

谢谢!

5

如果你需要创建长度不超过4个元素的序列,可以使用Seq类的工厂方法,如下所示:

Seq<String> seq1 =  new Set.Set1<>("s1").toSeq();
Seq<String> seq2 =  new Set.Set2<>("s1", "s2").toSeq();
Seq<String> seq3 =  new Set.Set3<>("s1", "s2", "s3").toSeq();
Seq<String> seq4 =  new Set.Set4<>("s1", "s2", "s3", "s4").toSeq();

4
import scala.collection.JavaConverters;
import scala.collection.Seq;

import java.util.ArrayList;

public class Helpers {
    public Seq<String> convertListToSeq(ArrayList<String> inputList) {
        return JavaConverters.collectionAsScalaIterableConverter(inputList).asScala().toSeq();
    }
}

版本 -

compile 'org.apache.spark:spark-core_2.11:2.3.1'
compile 'org.apache.spark:spark-sql_2.11:2.3.1'
compile group: 'commons-io', name: 'commons-io', version: '2.6'
compile "com.fasterxml.jackson.module:jackson-module-scala_2.11:2.8.8"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接