45

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.

Fundhor
  • 3,369
  • 1
  • 25
  • 47
  • 7
    Possible duplicate of [Converting a Java collection into a Scala collection](http://stackoverflow.com/questions/674713/converting-a-java-collection-into-a-scala-collection) – Tzach Zohar Mar 14 '16 at 13:04
  • 1
    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 Mar 14 '16 at 13:15
  • @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 Mar 14 '16 at 13:20
  • 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 implicits – Mateusz Dymczyk Mar 14 '16 at 13:31
  • "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 May 16 '17 at 13:04

7 Answers7

51

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();
}
Fundhor
  • 3,369
  • 1
  • 25
  • 47
24

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

Dima
  • 39,570
  • 6
  • 44
  • 70
  • 6
    `JavaConversions` is deprecated and now it should be written as `JavaConverters.asScalaBuffer(a)` – kap May 16 '17 at 12:09
  • _Should_ be? Nah ... Recommended by some unknown person who thought it was a better idea is more like it :) – Dima May 16 '17 at 12:54
  • 1
    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 ;-) – kap May 16 '17 at 12:59
16

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)
Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
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();
        }

}
Nikhil
  • 1,126
  • 12
  • 26
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 !

Community
  • 1
  • 1
Neeleshkumar S
  • 746
  • 11
  • 19
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();
loicmathieu
  • 5,181
  • 26
  • 31
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"
sapy
  • 8,952
  • 7
  • 49
  • 60