Convert Java List to Scala Seq
Asked Answered
V

7

48

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.

Varicose answered 14/3, 2016 at 13:2 Comment(5)
Possible duplicate of Converting a Java collection into a Scala collectionDepress
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.Lotuseater
@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...Varicose
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 implicitsStillmann
"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". :)Nicole
V
53

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();
}
Varicose answered 14/3, 2016 at 13:29 Comment(3)
Slightly shorter version: JavaConverters.asScalaIterableConverter(a).asScala().toSeq();Gesellschaft
JavaConverters.collectionAsScalaIterableConverter(list).asScala().toSeq() was the proper approach for me with Scala 2.12.6. There is also a JavaConverters.iterableAsScalaIterableConverter method if the source is an iterable instead of a collection.Pintsize
asScalaIteratorConverter (java.util.Iterator<A>) in JavaConverters cannot be applied to (scala.collection.Iterator<java.lang.String>) reason: no instance(s) of type variable(s) A exist so that Iterator<String> conforms to Iterator<ACalaboose
N
24

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

Nicole answered 14/3, 2016 at 13:48 Comment(3)
JavaConversions is deprecated and now it should be written as JavaConverters.asScalaBuffer(a)Maressa
Should be? Nah ... Recommended by some unknown person who thought it was a better idea is more like it :)Nicole
Probably. I just followed the hint in the Scala API. I do not know either of the persons who was writing and/or deprecating it ;-)Maressa
C
18

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)
Chatterer answered 29/3, 2019 at 21:39 Comment(0)
M
6

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

}
Moa answered 25/7, 2017 at 13:14 Comment(0)
I
5

@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 !

Injurious answered 24/10, 2016 at 9:30 Comment(0)
S
5

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();
Seek answered 13/3, 2017 at 15:17 Comment(0)
C
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();
    }
}

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"
Calaboose answered 16/1, 2020 at 16:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.