如何转换 Scala 集合类型?例如 Seq[Any] 到 Seq[(String, String)] 没有警告

How To Cast Scala Collection Types? Such As Seq[Any] to Seq[(String, String)] Without Warning

我想将 Scala 集合类型(例如 Seq[Any] 转换为 Seq[(String, String)],而不产生警告。

示例代码:

val seqs: Seq[Any] = Seq("1" -> "a", "2" -> "b")

def func(seqs: Seq[(String, String)]): String = {
}

func(seqs.asInstanceOf[Seq[(String, String)]]) // this will be warning

EDIT on 2018-10-18:

为了更好地理解我的问题,这是我的真实案例: 我有一个函数来处理带有参数 Seq[Any] 的东西,实际上,我希望这个参数的类型是 Seq[Int]Seq[(String, String)]:

def getColumns(specifiedSegs: Seq[Any] = Seq.empty): Set[(String, String)] = {
  if (specifiedSegs.isEmpty) {
    // load all kvs from api
    loadAllFromMetaApi() // this will return a Set[(String, String)]
  } else {
    specifiedSegs.head match {
      case _: Int => ... // let's omission this
      case _: (String, String) => specifiedSegs.asInstanceOf[Seq[(String, String)]].toSet // warning!
    }
  }
}

当我构建项目时,它会在 specifiedSegs.asInstanceOf[Seq[(String, String)]].toSet 上打印警告: warning: non-variable type argument String in type pattern (String, String) is unchecked since it is eliminated by erasure

不推荐使用asInstanceOf。您可以使用函数来实现更平滑的类型转换:

def seqOfAnyToSeqString(param : Seq[Any]) : Seq[(String, String)]
 = param.collect {
  case (x, y) => (x.toString, y.toString)
}

测试此功能:

val a  = Seq(1,2,3, 4 -> "b")
seqOfAnyToSeqString(a)

输出:

a: Seq[Any] = List(1, 2, 3, (4,b))
res0: Seq[(String, String)] = List((4,b))

所以它会默默地忽略序列中那些没有定义为元组的元素,而是将所有元组转换为字符串元组。当然,我假设输入相当简单,一个简单的 .toString 就足够了。

编辑:

或者,如评论中所建议的,如果您绝对确定该序列是 Seq[(String, String)] 的一个实例,您可以将上述函数 -using type ascriptions 编写为:

def seqOfAnyToSeqString(param : Seq[Any]) : Seq[(String, String)]
     = param.collect {
      case (x : String, y : String) => (x, y)
    }

但请注意,如果元素不符合 (String, String).

,这将丢弃元素

如果您想忽略所有非 (String, String) 元素,请参阅 。作为替代方案,如果您想在遇到非 (String, String) 元素时抛出特定错误,可以使用以下方法:

def convertSeq(seq: Seq[Any]): Seq[(String, String)] = seq map {
  case (x: String, y: String) => (x, y)
  case x => throw new IllegalArgumentException(s"$x is not type (String, String)")
}

例如:

scala> def convertSeq(seq: Seq[Any]): Seq[(String, String)] = seq map {
     |   case (x: String, y: String) => (x, y)
     |   case x => throw new IllegalArgumentException(s"$x is not type (String, String)")
     | }
convertSeq: (seq: Seq[Any])Seq[(String, String)]

scala> convertSeq(Seq(("abc", "def"), ("ghi", "jkl")))
res0: Seq[(String, String)] = List((abc,def), (ghi,jkl))

scala> convertSeq(Seq(1, 2, 3))
java.lang.IllegalArgumentException: 1 is not type (String, String)
  at $anonfun$convertSeq.apply(<console>:13)
  at $anonfun$convertSeq.apply(<console>:11)
  at scala.collection.TraversableLike$$anonfun$map.apply(TraversableLike.scala:245)
  at scala.collection.TraversableLike$$anonfun$map.apply(TraversableLike.scala:245)
  at scala.collection.immutable.List.foreach(List.scala:381)
  at scala.collection.TraversableLike$class.map(TraversableLike.scala:245)
  at scala.collection.immutable.List.map(List.scala:285)
  at .convertSeq(<console>:11)
  ... 33 elided