摘要: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")
}
}