scala scala-collections scala-java-interop

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>