检查地图标量的数据类型

时间:2018-03-12 21:20:44

标签: scala

我正在尝试写一些东西来检查Map的数据类型,由于某种原因,它不起作用,有人指出我做错了这里是代码

def mapTest() {

  var map= Map(1->"abc",2->20,3->(1 to 10 toList))

  map.foreach(a=>{a match {case a:(Int,String)=>"Int,String";case a:(Int,Int)=>"Int,Int";case a:(Int,List[Int])=>"Int,List"}})
}

2 个答案:

答案 0 :(得分:2)

如果您编译代码或稍微更清晰的代码:

map.foreach {
  case a: (Int, String) => println("Int,String")
  case a: (Int, Int) => println("Int,Int")
  case a: (Int, List[Int]) => println("Int,List")
}

您将看到编译器会针对每种情况发出警告:

  

警告:(66,15)非变量类型参数类型为模式(Int,String)的字符串未选中,因为它被擦除消除         case a:(Int,String)=>的println("诠释,字符串&#34)

这基本上意味着由于类型擦除,您不能尝试做的事情(即使用模式匹配来发现地图中元素的类型)。无法匹配元组元素的泛型类型。但是,有一个简单的解决方法:

map.foreach {
  case (a: Int, b: String) => println("Int,String")
  case (a: Int, b: Int) => println("Int,Int")
  case (a: Int, b: List[Int]) => println("Int,List")
}

这分别匹配每个元组元素的类型(使用元组' unapply方法)可以来克服类型擦除。

注意出于同样的原因,最后一种情况只能确保类型为(Int, List[_]) - 它会匹配任何类型的列表,而不仅仅是List[Int]

答案 1 :(得分:0)

可以通过使用ClassTags和TypeTags之类的东西来解决类型erasue以访问运行时类型。 Sinisa Louc提供了对不同标记之间差异以及它们可以和不可以使用的位置的完美解释。

让我把你的问题改为:

  •   

    我可以创建一个地图,其元素是异构的,并根据此类型执行不同的操作吗?

使用纯粹的scala来回答这个问题有点棘手,因为@Tzach Zohar提到它不容易与地图中的集合类型匹配,例如区分Map [Int,List [Int]]和Map [Int,List [String]]。

如果改为使用支持异构集合类型的库(例如shapeless),则可以使用此功能。

导入各种必需的库:

import shapeless._
import shapeless.record._
import shapeless.syntax.singleton._
import shapeless.labelled.{FieldType, field}

使用 - >>创建HList这会创建这些类型的安全密钥 - >价值对

val hmap =
    (1 ->> "hello") ::
        (2 ->> 2) ::
        (3 ->> true) ::
        (4 ->> (1 to 10).toList) ::
        (5 ->> List("this", "is","great")) ::
        HNil

创建一个多形态函数,用于提取类型信息:

object TypeInfo extends Poly1 {
    implicit def stringCase[F <: Int] = typeInfo[F, String]("String")
    implicit def intCase[F <: Int] = typeInfo[F, Int]("Int")
    implicit def boolCase[F <: Int] = typeInfo[F, Boolean]("Boolean")
    implicit def listIntCase[F <: Int] = typeInfo[F, List[Int]]("List[Int]")
    implicit def listStringCase[F <: Int] = typeInfo[F, List[String]]("List[String]")

    private def typeInfo[K <: Int, V](msg : String) =
      at[FieldType[K, V]] (_ => field[K](msg))
}

现在我们可以使用map函数映射值:

val typeInfo = hmap map TypeInfo

现在,您可以看到我们提取的所有不同类型:

typeInfo.values