java.util. Итератор для списка Scala? - PullRequest
17 голосов
/ 29 сентября 2011

У меня есть следующий код:

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 ]

25 голосов
/ 29 сентября 2011

Вам не нужно вызывать 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, но используют декораторы asScala / asJava в JavaConverters, чтобы сделать преобразования более явными.

11 голосов
/ 29 сентября 2011

Это сработало бы, если obj.getKeys () был java.util.Iterator<String>. Я полагаю, это не так.

Если obj.getKeys() это просто java.util.Iterator в необработанном виде, а не java.util.Iterator<String>, даже не java.util.Iterator<?>, это то, что scala имеет тенденцию не нравиться, но в любом случае, scala не будет печатать ваше выражение как List[String] если нет гарантии obj.getKeys() содержит строку.

Если вы знаете, что ваш итератор в строках, но тип этого не говорит, вы можете разыграть:

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

(затем продолжайте с .asScala.toList)

Обратите внимание, что, как и в java, и из-за стирания типа, это приведение не будет проверяться (вы получите предупреждение). Если вы хотите немедленно проверить, что у вас есть строки, вы можете сделать

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

, который будет проверять тип каждого элемента во время итерации для построения списка

3 голосов
/ 02 октября 2011

Мне не нравятся другие ответы.Черт, мне не нравится все, что предлагает использовать asInstanceOf, если нет альтернативы.В этом случае есть.Если вы сделаете это:

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

Вы превратите Iterator[_] в Iterator[String] безопасно и эффективно.

0 голосов
/ 01 апреля 2019

Обратите внимание, что начиная с Scala 2.13, пакет scala.jdk.CollectionConverters заменяет устаревшие пакеты scala.collection.JavaConverters/JavaConversions, когда речь идет о неявных преобразованиях между коллекциями Java и Scala:

import scala.jdk.CollectionConverters._

// val javaIterator: java.util.Iterator[String] = java.util.Arrays.asList("a", "b").iterator
javaIterator.asScala
// Iterator[String] = <iterator>
0 голосов
/ 12 декабря 2018

Начиная с версии 2.12.8 можно использовать

import scala.collection.JavaConverters._

asScalaIterator(java.util.Iterator variable).toSeq
...