java.util.Iterator到Scala列表?

时间:2011-09-28 21:03:29

标签: scala scala-collections scala-java-interop

我有以下代码:

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字符串列表,但(或许天真地)认为会有一个隐式转换。

5 个答案:

答案 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>