如何转换Scala集合类型?如Seq [Any]到Seq [(String,String)]而不发出警告

时间:2018-10-17 09:28:09

标签: scala scala-collections

我希望将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
  

在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

2 个答案:

答案 0 :(得分:2)

实际上不建议使用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)]的实例,则可以将上述函数-bug-编写为:

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

但是请注意,如果元素不符合(String, String),则会删除这些元素。

答案 1 :(得分:0)

如果要忽略所有非(String, String)元素,请参见jrook's answer。另外,如果遇到非(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$1.apply(<console>:13)
  at $anonfun$convertSeq$1.apply(<console>:11)
  at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:245)
  at scala.collection.TraversableLike$$anonfun$map$1.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