如何转换 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
我想将 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