web-dev-qa-db-ja.com

java.util.Iterator to Scala list?

私は次のコードを持っています:

private lazy val keys: List[String] = obj.getKeys().asScala.toList

obj.getKeysJava.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

TypeパラメーターまたはJavaイテレーターがJava文字列であり、Scala文字列のリストを作成しようとしていることを理解していますが、(おそらく単純に)暗黙の変換があるだろうと思った。

19
rshepherd

Obj.getKeys()が_Java.util.Iterator<String>_の場合、これは機能します。そうではないと思います。

obj.getKeys()が生の形式で_Java.util.Iterator_であり、_Java.util.Iterator<String>_ではなく、_Java.util.Iterator<?>_でさえない場合、これは何かscala嫌いになる傾向があります、しかしとにかく、obj.getKeys()に文字列が含まれているという保証がない場合、scalaは式を_List[String]_として入力する方法はありません。

イテレータが文字列上にあることがわかっているが、型がそう言っていない場合は、次のようにキャストできます。

_obj.getKeys().asInstanceOf[Java.util.Iterator[String]]
_

(その後、_.asScala.toList_を続行します)

Javaの場合と同様に、型消去のため、そのキャストはチェックされません(警告が表示されます)。文字列があることをすぐに確認したい場合は、むしろ行う

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

リストの作成を繰り返す間、各要素のタイプをチェックします

12
Didier Dupont

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デコレータを使用して、変換をより明示的にします。

25
Matthew Farwell

私は他の答えが嫌いです。地獄、私は代替手段がない限り、asInstanceOfの使用を提案するものは何でも嫌いです。この場合、あります。これを行う場合:

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

Iterator[_]Iterator[String]に安全かつ効率的に変換します。

3

scala 2.12.8の時点で、

import scala.collection.JavaConverters._

asScalaIterator(Java.util.Iterator variable).toSeq
0
Andriy

JavaコレクションとScalaコレクション間の暗黙的な変換に関しては、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>
0
Xavier Guihot