Java与Scala集合互转,Java中调用Scala集合,Sc
摘要:Scala,Java,JavaConverters
包括三种场景的转化
- Java脚本中,将Scala集合转化为Java集合
 - Scala脚本中,将Scala集合转化为Java集合
 - Scala脚本中,将Java集合转化为Scala集合
 
JavaConverters隐式转换
Scala提供了大量的方法来隐式转换所有主要的Java和Scala容器类型。其中提供了如下的双向类型转换
Iterator<=>java.util.Iterator
Iterator<=>java.util.Enumeration
Iterable<=>java.lang.Iterable
Iterable<=>java.util.Collection
mutable.Buffer<=>java.util.List
mutable.Set<=>java.util.Set
mutable.Map<=>java.util.Map
mutable.ConcurrentMap<=>java.util.concurrent.ConcurrentMap
使用这些转换很简单,只需从JavaConverters对象中import它们即可。import之后,通过扩展方法 asScala 和 asJava 就可以在Scala容器和与之对应的Java容器之间进行隐式转换了
scala> import collection.JavaConverters._
import collection.JavaConverters._
还有一些Scala容器类型可以转换成对应的Java类型,但是并没有将相应的Java类型转换成Scala类型的能力,它们是:
Seq=>java.util.List
mutable.Seq=>java.util.List
Set=>java.util.Set
Map=>java.util.Map
因为Java并未区分可变容器不可变容器类型,所以,虽然能将scala.immutable.List转换成java.util.List,但所有的修改操作都会抛出“UnsupportedOperationException”
scala> val jul = List(1, 2, 3).asJava
jul: java.util.List[Int] = [1, 2, 3]
scala> jul.add(7)
java.lang.UnsupportedOperationException
  at java.util.AbstractList.add(AbstractList.java:148)
在Java中调用使用Scala集合
Scala List => Java List
在Scala中定义方法返回List,在Java中调用得到返回值并转化为Java的list。
object ReturnScalaCollection {
  def returnList(): List[String] = {
    return List("a", "b", "c")
  }
  def returnListType(): List[Int] = {
    return List(1, 2, 3)
  }
}
Scala list调用apply方法获得下标元素,循环一遍得到Java list,如果不是String对象,Java中得到的返回值泛型是Object,通过类型强转得到对应类型
public static void main(String[] args) {
        scala.collection.immutable.List<String> res = ReturnScalaCollection.returnList();
        List<String> list = new ArrayList<>();
        for (int i = 0; i < res.size(); i ++) {
            list.add(res.apply(i));
        }
        System.out.println(list);  // [a, b, c]
        scala.collection.immutable.List<Object> res2 = ReturnScalaCollection.returnListType();
        List<Integer> list2 = new ArrayList<>();
        for (int i = 0; i < res2.size(); i ++) {
            list2.add((int) res2.apply(i));
        }
        System.out.println(list2);  // [1, 2, 3]
    }
Scala Map => Java Map
Scala转List<Tuple2<>>,使用下标访问填充到Java Map。
def returnMap(): Map[String, Int] = {
    return Map("a" -> 1, "b" -> 2)
  }
public static void main(String[] args) {
        scala.collection.immutable.Map<String, Object> res3 = ReturnScalaCollection.returnMap();
//        scala.collection.immutable.List<Tuple2<String, Object>> res3List = res3.toList();
        Map<String, Integer> map = new HashMap<>();
        for (int i = 0; i < res3.size(); i ++) {
            map.put(res3.toList().apply(i)._1(), (int) res3.toList().apply(i)._2());  // {a=1, b=2}
        }
        System.out.println(map);
    }
Scala Set => Java Set
Scala转List,Java通过下标apply获取值填充到Set。
def returnSet(): Set[String] = {
    return Set("a", "b", "a")
  }
public static void main(String[] args) {
        scala.collection.immutable.Set<String> res4 = ReturnScalaCollection.returnSet();
        Set<String> set = new HashSet<>();
        for (int i = 0; i < res4.size(); i ++) {
            System.out.println(res4.toList().apply(i));
            set.add(res4.toList().apply(i));
        }
        System.out.println(set);  // [a, b]
    }
Scala Tuple => Java
在Java中指定Tuple类型和对应泛型,如果飞String需要强转,使用_1()访问,不带()可能报null
def returnTuple(): (String, String) = {
    val a = "a"
    val b = "b"
    return (a, b)
  }
  def returnTuple2(): (Int, Boolean) = {
    val a = 1
    val b = false
    return (a, b)
  }
public static void main(String[] args) {
        scala.Tuple2<String, String> res = TupleTest.returnTuple();
        String a = res._1();  // a
        String b = res._2();  // b
        scala.Tuple2<Object, Object> res2 = TupleTest.returnTuple2();
        int aa = (int) res2._1();  // 1
        boolean bb = (boolean) res2._2();  // false
    }
在Scala中转化Java集合(scala -> Java; Java -> Scala)
分为两种情况,将Scala的集合转化为Java集合,使得可以调用Java方法;将Java集合转化为Scala集合
Scala中,将Scala的集合转化为Java集合
在Java中创建传参分别是Java List,Map,Set的方法,在Scala中创建集合调用,使用JavaConverters进行隐式转换,如果单向转 Scala => Java,Scala集合可变不可变都可以,如果要双向转Scala集合必须是mutable可变的,否则Java转Scala不报错但是不能再执行修改增加操作。
import java.util
import scala.collection.mutable
import scala.collection.mutable.ListBuffer
object ScalaJavaTest {
  def JavaList2ScalaList(): Unit = {
    import scala.collection.JavaConverters._
    // scala List => java.util.List
    val a: java.util.List[String] = List("a", "b", "c").asJava
    val b: java.util.List[String] = ListBuffer("a", "b", "c").asJava
    val c: java.util.Collection[String] = List("a", "b", "c").asJava
    val f: java.util.List[String] = mutable.Buffer[String]("a", "b").asJava
    // java.util.List => scala.collection.mutable.Buffer
    val aa: scala.collection.mutable.Buffer[String] = b.asScala
    val bb: scala.collection.mutable.ListBuffer[String] = a.asScala.to[ListBuffer]
    val cc: scala.collection.immutable.List[String] = a.asScala.toList
    // java.util.ArrayList => scala
    val e = new util.ArrayList[String](util.Arrays.asList("a", "b", "c"))
    val ee: scala.collection.mutable.ListBuffer[String] = e.asScala.to[ListBuffer]
  }
  def JavaMap2ScalaMap(): Unit = {
    import scala.collection.JavaConverters._
    // scala Map => java.util.Map
    val a: java.util.Map[String, Int] = Map("a" -> 1, "b" -> 2).asJava
    val c: java.util.Map[String, Int] = mutable.HashMap[String, Int]("a" -> 1, "b" -> 2).asJava
    println(a)
    println(c)
    // java.util.Map => java.util.HashMap
    val b = new util.HashMap[String, Int](a)
    b.put("c", 3)
    // java.util.Map => scala.collection.mutable.Map
    val aa: scala.collection.mutable.Map[String, Int] = a.asScala
    println(aa.getOrElse("b", -1))
    // 报错
    //    aa.put("c", 3)
    //    println(aa)
    // 转可变Map
    val aaa = mutable.Map(aa.toSeq:_*)
    aaa.put("c", 3)
    println(aaa)
    val bb: scala.collection.mutable.Map[String, Int] = b.asScala
    bb.put("c", 3)
    println(bb)
    // java.util.HashMap => scala
    val d = new util.HashMap[String, Int]()
    d.put("a", 1)
    d.put("b", 2)
    val dd: scala.collection.mutable.Map[String, Int] = d.asScala
    dd.put("c", 3)
    println(dd)
  }
  def JavaSet2ScalaSet(): Unit = {
    import scala.collection.JavaConverters._
    // scala Set => java.util.Set
    val a: java.util.Set[String] = Set("a", "b").asJava
    println(a)
    // java.util.Set => java.util.HashSet
    val b = new util.HashSet[String](a)
    b.add("c")
    println(b)
    // java.util.Set => scala.collection.mutable.Set
    val aa: scala.collection.mutable.Set[String] = a.asScala
    println(aa)
    // 报错
    //    aa.add("c")
    //    println(aa)
    // 转可变Set
    val aaa = mutable.Set(aa.toSeq:_*)
    aaa.add("c")
    val bb: scala.collection.mutable.Set[String] = b.asScala
    bb.add("c")
  }
}