java.util.Iterator to Scala list?

前端 未结 5 1640
走了就别回头了
走了就别回头了 2021-02-12 13:16

I have the following code:

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

obj.getKeys returns a java.uti

相关标签:
5条回答
  • 2021-02-12 13:59

    I dislike the other answers. Hell, I dislike anything that suggests using asInstanceOf unless there's no alternative. In this case, there is. If you do this:

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

    You turn the Iterator[_] into a Iterator[String] safely and efficiently.

    0 讨论(0)
  • 2021-02-12 14:05

    Note that starting Scala 2.13, package scala.jdk.CollectionConverters replaces deprecated packages scala.collection.JavaConverters/JavaConversions when it comes to implicit conversions between Java and Scala collections:

    import scala.jdk.CollectionConverters._
    
    // val javaIterator: java.util.Iterator[String] = java.util.Arrays.asList("a", "b").iterator
    javaIterator.asScala
    // Iterator[String] = <iterator>
    
    0 讨论(0)
  • 2021-02-12 14:06

    That would work if obj.getKeys() was a java.util.Iterator<String>. I suppose it is not.

    If obj.getKeys() is just java.util.Iterator in raw form, not java.util.Iterator<String>, not even java.util.Iterator<?>, this is something scala tend to dislikes, but anyway, there is no way scala will type your expression as List[String] if it has no guarantee obj.getKeys() contains String.

    If you know your iterator is on Strings, but the type does not say so, you may cast :

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

    (then go on with .asScala.toList)

    Note that, just as in java and because of type erasure, that cast will not be checked (you will get a warning). If you want to check immediately that you have Strings, you may rather do

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

    which will check the type of each element while you iterate to build the list

    0 讨论(0)
  • 2021-02-12 14:07

    As of scala 2.12.8 one could use

    import scala.collection.JavaConverters._
    
    asScalaIterator(java.util.Iterator variable).toSeq
    
    0 讨论(0)
  • 2021-02-12 14:18

    You don't need to call asScala, it is an implicit conversion:

    import scala.collection.JavaConversions._
    
    val javaList = new java.util.LinkedList[String]() // as an example
    
    val scalaList = javaList.iterator.toList
    

    If you really don't have the type parameter of the iterator, just cast it to the correct type:

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

    EDIT: Some people prefer not to use the implicit conversions in JavaConversions, but use the asScala/asJava decorators in JavaConverters to make the conversions more explicit.

    0 讨论(0)
提交回复
热议问题