37
votes

I need to implement a method that returns a Scala Seq, in Java.

But I encounter this error:

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

Here is my code so far:

@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;
}

But scala.collection.JavaConverters doesn't seem to offer the possibility to convert as a Seq.

7
You're asking for trouble if you try to do anything with Scala collections in Java. Write a bit of Scala code which does the conversion using scala.collection.JavaConverters.Luigi Plinge
@TzachZohar most of the answer are done is scala. My code is Java, it's part of a huge program, I can't externalize this treatment...Fundhor
As @LuigiPlinge mentioned this is not a good idea! You'll probably have a lot of problems trying to invoke method on this sequence, god forbid you try invoking anything that requires implicitsMateusz Dymczyk
"they can result in unexpected behavior and performance" in the docs doesn't sound very convincing ... especially, since the very next sentence suggests JavaConverters that "offer the same conversions". :)Dima

7 Answers

44
votes

JavaConverters is what I needed to solve this.

import scala.collection.JavaConverters;

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

JavaConversions should work. I think, you are looking for something like this: JavaConversions.asScalaBuffer(a).toSeq()

8
votes

Starting Scala 2.13, package scala.jdk.javaapi.CollectionConverters replaces deprecated packages 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
votes

This worked for me! (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
votes

@Fundhor, the method asScalaIterableConverter was not showing up in the IDE. It may be due to a difference in the versions of Scala. I am using Scala 2.11. Instead, it showed up asScalaIteratorConverter. I made a slight change to your final snippet and it worked fine for me.

scala.collection.JavaConverters.asScalaIteratorConverter(columnNames.iterator()).asScala().toSeq() where columnNames is a java.util.List.

thanks !

4
votes

Up to 4 elements, you can simply use the factory method of the Seq class like this :

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();
3
votes
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();
    }
}

Versions -

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"