java.util.Iterador a la lista de Scala?
scala-collections scala-java-interop (5)
A partir de Scala 2.12.8 uno podría usar
import scala.collection.JavaConverters._
asScalaIterator(java.util.Iterator variable).toSeq
Tengo el siguiente código:
private lazy val keys: List[String] = obj.getKeys().asScala.toList
obj.getKeys
devuelve un java.util.Iterator<java.lang.String>
Llamar a asScala
, a través de JavaConverers
(que se importa) de acuerdo con los documentos.
java.util.Iterator <==> scala.collection.Iterator
scala.collection.Iterator
define
def toList: List[A]
Así que en base a esto, creí que esto debería funcionar, sin embargo aquí está el error de compilación:
[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
Entiendo que el parámetro de tipo o el Iterador de Java es una cadena Java, y que estoy tratando de crear una lista de cadenas Scala, pero (tal vez ingenuamente) pensé que habría una conversión implícita.
Eso funcionaría si obj.getKeys () fuera un java.util.Iterator<String>
. Supongo que no lo es.
Si obj.getKeys()
es simplemente java.util.Iterator
en formato sin formato, no java.util.Iterator<String>
, ni siquiera java.util.Iterator<?>
, Esto es algo que a scala no le gusta, pero de todos modos, hay de ninguna manera scala escribirá su expresión como List[String]
si no tiene garantía obj.getKeys()
contiene String.
Si sabe que su iterador está en cadenas, pero el tipo no lo dice, puede lanzar:
obj.getKeys().asInstanceOf[java.util.Iterator[String]]
(luego continúa con .asScala.toList
)
Tenga en cuenta que, al igual que en java y debido al borrado de tipo, ese lanzamiento no se verificará (aparecerá una advertencia). Si desea comprobar de inmediato que tiene cadenas, puede hacerlo
obj.getKeys().map(_.asInstanceOf[String])
que verificará el tipo de cada elemento mientras iteras para construir la lista
No me gustan las otras respuestas. Demonios, no me gusta nada que sugiera usar asInstanceOf
menos que no haya otra alternativa. En este caso, hay. Si haces esto:
private lazy val keys : List[String] = obj.getKeys().asScala.collect {
case s: String => s
}.toList
Iterator[_]
el Iterator[_]
en un Iterator[String]
forma segura y eficiente.
No necesitas llamar a asScala, es una conversión implícita:
import scala.collection.JavaConversions._
val javaList = new java.util.LinkedList[String]() // as an example
val scalaList = javaList.iterator.toList
Si realmente no tiene el parámetro de tipo del iterador, simplemente cámbielo al tipo correcto:
javaList.iterator.asInstanceOf[java.util.Iterator[String]].toList
EDITAR: Algunas personas prefieren no usar las conversiones implícitas en JavaConversions, pero usan los decoradores asScala / asJava en JavaConverters para hacer las conversiones más explícitas.
Tenga en cuenta que al iniciar Scala 2.13
, el paquete scala.jdk.CollectionConverters
reemplaza a los paquetes obsoletos scala.collection.JavaConverters/JavaConversions
cuando se trata de conversiones implícitas entre las colecciones Java y Scala:
import scala.jdk.CollectionConverters.Ops._
// val javaIterator: java.util.Iterator[String] = java.util.Arrays.asList("a", "b").iterator
javaIterator.asScala
// Iterator[String] = <iterator>