我有以下代码:
private lazy val keys: List[String] = obj.getKeys().asScala.toList
obj.getKeys
返回java.util.Iterator<java.lang.String>
根据文档通过asScala
(已导入)调用JavaConverers
..
java.util.Iterator <==> scala.collection.Iterator
scala.collection.Iterator
定义
def toList: List[A]
基于此,我相信这应该可行,但这里是编译错误:
[scalac] <file>.scala:11: error: type mismatch;
[scalac] found : List[?0] where type ?0
[scalac] required: List[String]
[scalac] private lazy val keys : List[String] = obj.getKeys().asScala.toList
[scalac] one error found
我理解类型参数或java Iterator是一个Java字符串,我试图创建一个Scala字符串列表,但(或许天真地)认为会有一个隐式转换。
答案 0 :(得分:25)
您不需要调用asScala,它是隐式转换:
import scala.collection.JavaConversions._
val javaList = new java.util.LinkedList[String]() // as an example
val scalaList = javaList.iterator.toList
如果你真的没有迭代器的type参数,只需将其强制转换为正确的类型:
javaList.iterator.asInstanceOf[java.util.Iterator[String]].toList
编辑:有些人不喜欢在JavaConversions中使用隐式转换,而是使用JavaConverters中的asScala / asJava装饰器来使转换更加明确。
答案 1 :(得分:11)
如果obj.getKeys()是java.util.Iterator<String>
,那将会有效。我想它不是。
如果obj.getKeys()
只是java.util.Iterator
原始形式,而不是java.util.Iterator<String>
,甚至不是java.util.Iterator<?>
,这是scala不喜欢的东西,但无论如何,没有办法如果scala无法保证List[String]
包含String,则会将表达式键入obj.getKeys()
。
如果您知道您的迭代器是在字符串上,但类型没有这样说,您可以强制转换:
obj.getKeys().asInstanceOf[java.util.Iterator[String]]
(然后继续.asScala.toList
)
请注意,就像在java中一样,因为类型擦除,不会检查该强制转换(您将收到警告)。如果你想立即检查你有字符串,你可能宁愿做
obj.getKeys().map(_.asInstanceOf[String])
将在您迭代构建列表时检查每个元素的类型
答案 2 :(得分:3)
我不喜欢其他答案。天哪,我不喜欢任何暗示使用asInstanceOf
的东西,除非别无选择。在这种情况下,有。如果你这样做:
private lazy val keys : List[String] = obj.getKeys().asScala.collect {
case s: String => s
}.toList
您可以安全有效地将Iterator[_]
转换为Iterator[String]
。
答案 3 :(得分:0)
从scala 2.12.8开始,人们可以使用
import scala.collection.JavaConverters._
asScalaIterator(java.util.Iterator variable).toSeq
答案 4 :(得分:0)
请注意,在Java和Scala集合之间进行隐式转换时,从Scala 2.13
开始,软件包scala.jdk.CollectionConverters
会替换已弃用的软件包scala.collection.JavaConverters/JavaConversions
:
import scala.jdk.CollectionConverters.Ops._
// val javaIterator: java.util.Iterator[String] = java.util.Arrays.asList("a", "b").iterator
javaIterator.asScala
// Iterator[String] = <iterator>