使用通用键和值从映射中获取实际类型
Get actually type from map with generic keys and values
首先是一些 Scala 代码示例:
trait Key[+T]
trait Value[+T]
case class StringKey(key: String) extends Key[String]
case class IntKey(key: Int) extends Key[Int]
case class StringValue(value: String) extends Value[String]
case class IntValue(value: Int) extends Value[Int]
case class ValueHolder(sources: Map[Key[_], Value[_]]) {
def processSources(): Unit = {
sources.map{ case (key, value) =>
// get actual key and value, and process
}
}
}
基本上我有一个从通用键到通用值的映射,我需要迭代键值对并对实际对象进行操作。例如,如果当前值实际上是一个 StringValue
,我想对一个 StringValue
对象进行操作。有办法吗?
是的。当出现 StringValue
时,使用模式匹配或使用 Partial 函数收集结果。
首先,我认为您错过了 StringKey extends Key[String]
、T
的协方差等...
下面的代码告诉我们需要什么。
trait Key[+T]
trait Value[+T]
case class StringKey(key: String) extends Key[String]
case class IntKey(key: Int) extends Key[Int]
case class StringValue(value: String) extends Value[String]
case class IntValue(value: Int) extends Value[Int]
假设上述情况
case class ValueHolder(sources: Map[Key[_], Value[_]]) {
def processSources(): Unit = {
sources
.collect { case (_, StringValue(str)) => str }
.foreach(println)
}
}
Scala REPL
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait Key[+T]
trait Value[+T]
case class StringKey(key: String) extends Key[String]
case class IntKey(key: Int) extends Key[Int]
case class StringValue(value: String) extends Value[String]
case class IntValue(value: Int) extends Value[Int]
// Exiting paste mode, now interpreting.
defined trait Key
defined trait Value
defined class StringKey
defined class IntKey
defined class StringValue
defined class IntValue
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class ValueHolder(sources: Map[Key[_], Value[_]]) {
def processSources(): Unit = {
sources
.collect { case (_, StringValue(str)) => str } // extracted string value ready to be operated.
.foreach(println)
}
}
// Exiting paste mode, now interpreting.
defined class ValueHolder
输出
scala> ValueHolder(Map(StringKey("fruit") -> StringValue("apple")))
res2: ValueHolder = ValueHolder(Map(StringKey(fruit) -> StringValue(apple)))
scala> ValueHolder(Map(StringKey("fruit") -> StringValue("apple"))).processSources()
apple
通常你可以迭代键值对
给定 sources: Map[Key[_], Value[_]]
如果值为字符串值则处理
sources.map { case (key, value) =>
value match {
case stringValue: StringValue => processValue(stringValue)
case _ => fallbackValue
}
}
更好的方法是使用 collect
sources.collect { case (_, value: StringValue) => processValue(value) }
首先是一些 Scala 代码示例:
trait Key[+T]
trait Value[+T]
case class StringKey(key: String) extends Key[String]
case class IntKey(key: Int) extends Key[Int]
case class StringValue(value: String) extends Value[String]
case class IntValue(value: Int) extends Value[Int]
case class ValueHolder(sources: Map[Key[_], Value[_]]) {
def processSources(): Unit = {
sources.map{ case (key, value) =>
// get actual key and value, and process
}
}
}
基本上我有一个从通用键到通用值的映射,我需要迭代键值对并对实际对象进行操作。例如,如果当前值实际上是一个 StringValue
,我想对一个 StringValue
对象进行操作。有办法吗?
是的。当出现 StringValue
时,使用模式匹配或使用 Partial 函数收集结果。
首先,我认为您错过了 StringKey extends Key[String]
、T
的协方差等...
下面的代码告诉我们需要什么。
trait Key[+T]
trait Value[+T]
case class StringKey(key: String) extends Key[String]
case class IntKey(key: Int) extends Key[Int]
case class StringValue(value: String) extends Value[String]
case class IntValue(value: Int) extends Value[Int]
假设上述情况
case class ValueHolder(sources: Map[Key[_], Value[_]]) {
def processSources(): Unit = {
sources
.collect { case (_, StringValue(str)) => str }
.foreach(println)
}
}
Scala REPL
scala> :paste
// Entering paste mode (ctrl-D to finish)
trait Key[+T]
trait Value[+T]
case class StringKey(key: String) extends Key[String]
case class IntKey(key: Int) extends Key[Int]
case class StringValue(value: String) extends Value[String]
case class IntValue(value: Int) extends Value[Int]
// Exiting paste mode, now interpreting.
defined trait Key
defined trait Value
defined class StringKey
defined class IntKey
defined class StringValue
defined class IntValue
scala> :paste
// Entering paste mode (ctrl-D to finish)
case class ValueHolder(sources: Map[Key[_], Value[_]]) {
def processSources(): Unit = {
sources
.collect { case (_, StringValue(str)) => str } // extracted string value ready to be operated.
.foreach(println)
}
}
// Exiting paste mode, now interpreting.
defined class ValueHolder
输出
scala> ValueHolder(Map(StringKey("fruit") -> StringValue("apple")))
res2: ValueHolder = ValueHolder(Map(StringKey(fruit) -> StringValue(apple)))
scala> ValueHolder(Map(StringKey("fruit") -> StringValue("apple"))).processSources()
apple
通常你可以迭代键值对
给定 sources: Map[Key[_], Value[_]]
如果值为字符串值则处理
sources.map { case (key, value) =>
value match {
case stringValue: StringValue => processValue(stringValue)
case _ => fallbackValue
}
}
更好的方法是使用 collect
sources.collect { case (_, value: StringValue) => processValue(value) }