为什么我有类型不匹配异常?

时间:2014-01-13 18:31:41

标签: scala

我在这个片段中有一个奇怪的例外

 val splitted = "This is a text that to test something".split("\\,|\\ ")
 val map = mutable.Map[Int, List[String]]()
 (0 to splitted.length).foreach {
     case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
 }

但我有这个例外:

type mismatch;
 found   : List[Any]
 required: List[String]
      case i =>map(i) = map.getOrElse(i,List("")) ++ splitted(i)
                                              ^                                                  ^

4 个答案:

答案 0 :(得分:2)

splitted(i)String++(需要集合)会将字符串视为Array[Char],然后会产生公共超类型List[Any]。< / p>

示例:

val list = List("a", "b") ++ "hello"
println(list) //prints List(a, b, h, e, l, l, o) and is of type List[Any]

如果它插入的位置无关紧要,那么我会这样做:

case i => map(i) = splitted(i) :: map.getOrElse(i,List[String](""))

如果应该追加:

case i => map(i) = map.getOrElse(i,List[String]("")) :+ splitted(i)

答案 1 :(得分:2)

你是Any推理的另一个受害者。

scala> map.getOrElse(7,List[String](""))
res3: List[String] = List("")

scala> res3 ++ "abc"
res4: List[Any] = List("", a, b, c)

这与-Xlint

相同
scala> (0 to splitted.length).foreach {
     case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
 }
<console>:12: error: type mismatch;
 found   : List[Any]
 required: List[String]
                   case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
                                                                       ^

scala> val res3 = { map.getOrElse(7,List[String]("")) }
<console>:6: warning: Unused import
import collection.mutable
                  ^
res3: List[String] = List("")

scala> res3 ++ "abc"
<console>:11: warning: a type was inferred to be `Any`; this may indicate a programming error.
              res3 ++ "abc"
                      ^
res1: List[Any] = List("", a, b, c)

不幸的是,错误会使-Xlint警告窒息。

而且,在-Xlint -Xfatal-warnings下,警告没有机会出错:

scala> (0 to splitted.length).foreach {
     case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
 }
<console>:11: error: type mismatch;
 found   : List[Any]
 required: List[String]
                   case i =>map(i) = map.getOrElse(i,List[String]("")) ++ splitted(i)
                                                                       ^

如果警告不在闭包内,那么您将收到-Xlint -Xfatal-warnings下的有用信息:

val ss: List[String] = (null: mutable.Map[Int,List[String]]).getOrElse(0,List.empty[String]) ++ "abc"

答案 2 :(得分:1)

不确定您要对该代码执行什么操作,但这是一个可用的版本:

(0 to splitted.length-1).foreach {
  case i =>map(i) = (map.getOrElse(i,List[String]("")) :+ splitted(i))
}

将创建:

println(map)
Map(2 -> List(, a), 5 -> List(, to), 4 -> List(, that), 7 -> List(, something), 1 -> List(, is), 3 -> List(, text), 6 -> List(, test), 0 -> List(, This))

编辑:也许你需要的是以下内容:

splitted.zipWithIndex.map{case (s,i)=>(i,s)}.toMap

导致:

Map(0 -> This, 5 -> to, 1 -> is, 6 -> test, 2 -> a, 7 -> something, 3 -> text, 4 -> that)

或更有效率:

((0 to splitted.length-1) zip splitted).toMap

答案 3 :(得分:0)

这很有效。

 val splitted = "This is a text that to test something".split("\\,|\\ ")
 val map = scala.collection.mutable.Map[Int, List[String]]()
 (0 until splitted.length).foreach {
     case i =>map(i) = map.getOrElse(i,List[String]("")) :+ splitted(i)
 }

哪个输出:

scala.collection.mutable.Map[Int,List[String]] = Map(2 -> List("", a), 5 -> List("", to), 4 -> List("", that), 7 -> List("", something), 1 -> List("", is), 3 -> List("", text), 6 -> List("", test), 0 -> List("", This))

另请注意tountil之间的区别。使用to in将提供ArrayOutOfBoundsException

scala> val l = List(1,2,3)
l: List[Int] = List(1, 2, 3)
scala> 0 to l.length
res51: scala.collection.immutable.Range.Inclusive = Range(0, 1, 2, 3)
scala> 0 until l.length
res52: scala.collection.immutable.Range = Range(0, 1, 2)