Scala Map.mapValues stackoverflowerror [英] Scala Map.mapValues stackoverflowerror

查看:48
本文介绍了Scala Map.mapValues stackoverflowerror的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下代码导致最后一行出现 StackOverflowError.

The following code results in a StackOverflowError on the last line.

object StackTest extends App{
    @tailrec def incrementValues(acc: Map[String, Int], inc: Int): Map[String, Int] = {
        if(inc == 0) acc
        else incrementValues(acc.mapValues(_ + 1), inc - 1)
    }

    val myMap = incrementValues(Map("key" -> 0), 10000)
    myMap.foreach(println)
}

在 Scala 2.11.2 中:

In Scala 2.11.2:

Exception in thread "main" java.lang.StackOverflowError
at scala.collection.MapLike$MappedValues.foreach(MapLike.scala:245)
at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:777)
at scala.collection.MapLike$MappedValues.foreach(MapLike.scala:245)
at scala.collection.TraversableLike$WithFilter.foreach(TraversableLike.scala:777)
at scala.collection.MapLike$MappedValues.foreach(MapLike.scala:245)
...

查看 MapLike 的源代码,我可以看到它使用的是 MappedValues 对象,这看起来像一个视图:

Looking at the source for MapLike I can see it's using a MappedValues object, which seems like a view:

  protected class MappedValues[C](f: B => C) extends AbstractMap[A, C] with DefaultMap[A, C] {
    override def foreach[D](g: ((A, C)) => D): Unit = for ((k, v) <- self) g((k, f(v)))
    def iterator = for ((k, v) <- self.iterator) yield (k, f(v))
    override def size = self.size
    override def contains(key: A) = self.contains(key)
    def get(key: A) = self.get(key).map(f)
  }

  /** Transforms this map by applying a function to every retrieved value.
   *  @param  f   the function used to transform values of this map.
   *  @return a map view which maps every key of this map
   *          to `f(this(key))`. The resulting map wraps the original map without copying any elements.
   */
  def mapValues[C](f: B => C): Map[A, C] = new MappedValues(f)

使它实际映射值的最佳方法是什么?

What's the best way to make it actually map the values?

推荐答案

mapValues 被认为是一个陷阱,因为它确实只创建了一个包装视图函数,而不是急切地生成一个新集合.因此,在您的示例中,您创建了一个嵌套级别为 10,000 的数据结构.

mapValues is known to be a trap, as it indeed creates only a wrapping view function instead of eagerly producing a new collection. Therefore, in your example you create a data structure of nesting level 10,000.

您可以使用常规的 map 方法:

You can use the regular map method:

acc.map(tup => (tup._1, tup._2 + 1))

acc.map { case (key, value) => (key, value + 1) }

这篇关于Scala Map.mapValues stackoverflowerror的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆