我正在尝试为scala中的java集合编写一个“解构器”。
对于大多数 scala 集合,我可以使用::
case 类来解构 head/tail 中的集合:
scala> val (a :: b) = Seq(1,2)
a: Int = 1
b: List[Int] = List(2)
scala> val (a :: b :: Nil) = Seq(1,2)
a: Int = 1
b: Int = 2
甚至更复杂的情况(例如,将内部列表的两个第一个元素相加):
scala> val m = Map("a" -> Seq(1,2,3,4), "b" -> Seq(2,3,4,5))
scala> m.collect { case (k, a :: b :: _) => k ->(a+b)}
res5: scala.collection.immutable.Map[java.lang.String,Int] = Map(a -> 3, b -> 5)
但我无法弄清楚如何在没有多余代码的情况下为 java 集合进行这项工作:
假设我从一个外部库中得到这样的东西:
m: java.util.Map[java.lang.String,java.util.List[Int]] = {a=[1, 2, 3, 4], b=[2, 3, 4, 5]}
使用 scala<=>java 集合转换,我可以将映射转换为 scala 映射,并处理内部列表,这些列表仍然是 java 列表:
m.asScala.collect { case (k, jl) => jl.asScala.toList match { case (a :: b :: _) => k->(a+b) } }
或者
m.asScala.map{
case (k, v) => k -> v.asScala.toList
}.collect {
case (k, a :: b :: _) => k ->(a+b)
}
我找到了unapplySeq
匹配器技巧,但这仅在我知道集合的大小时才有效:
object JavaCollection {
import scala.collection.JavaConverters._
def unapplySeq[T](array: java.util.Collection[T]): Option[Seq[T]] = Option(array).map(_.asScala.toIndexedSeq)
}
m.asScala.collect { case (k, JavaCollection(a,b,c,d)) => k ->(a+b)}
如何在::
不经过显式转换的情况下让解构直接在 Java 类型化集合上工作?我尝试过建立自己的case class ::[T](head:T, tail: java.util.Collection[T])
课程,但这似乎还不够。