20

我有以下代码:

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

4

5 回答 5

26

您不需要调用 asScala,它是一种隐式转换:

import scala.collection.JavaConversions._

val javaList = new java.util.LinkedList[String]() // as an example

val scalaList = javaList.iterator.toList

如果您真的没有迭代器的类型参数,只需将其转换为正确的类型:

javaList.iterator.asInstanceOf[java.util.Iterator[String]].toList

编辑:有些人不喜欢在 JavaConversions 中使用隐式转换,而是在 JavaConverters 中使用 asScala/asJava 装饰器来使转换更加明确。

于 2011-09-28T21:19:33.767 回答
11

如果 obj.getKeys() 是一个java.util.Iterator<String>. 我想不是。

If obj.getKeys()is just java.util.Iteratorin raw form, not java.util.Iterator<String>, even java.util.Iterator<?>, 这是 scala 不喜欢的东西,但无论如何,scala 不会输入你的表达式,就List[String]好像它不能保证obj.getKeys()包含字符串一样。

如果你知道你的迭代器在字符串上,但类型没有这样说,你可以强制转换:

obj.getKeys().asInstanceOf[java.util.Iterator[String]]

(然后继续.asScala.toList

请注意,就像在 java 中一样,并且由于类型擦除,不会检查该强制转换(您将收到警告)。如果你想立即检查你是否有字符串,你可能宁愿做

obj.getKeys().map(_.asInstanceOf[String])

这将在您迭代构建列表时检查每个元素的类型

于 2011-09-28T21:39:42.913 回答
3

我不喜欢其他答案。地狱,我不喜欢任何建议使用asInstanceOf的东西,除非别无选择。在这种情况下,有。如果你这样做:

private lazy val keys : List[String] = obj.getKeys().asScala.collect { 
    case s: String => s 
}.toList

你把它Iterator[_]变成一个Iterator[String]安全有效的。

于 2011-10-01T23:02:36.597 回答
2

请注意,当涉及到 Java 和 Scala 集合之间的隐式转换时,starting Scala 2.13, package会scala.jdk.CollectionConverters替换不推荐使用的包:scala.collection.JavaConverters/JavaConversions

import scala.jdk.CollectionConverters._

// val javaIterator: java.util.Iterator[String] = java.util.Arrays.asList("a", "b").iterator
javaIterator.asScala
// Iterator[String] = <iterator>
于 2019-03-31T21:12:19.713 回答
0

从 scala 2.12.8 开始,可以使用

import scala.collection.JavaConverters._

asScalaIterator(java.util.Iterator variable).toSeq
于 2018-12-12T16:34:55.137 回答