Scala:如何从地图制作Hash(Trie)Map(通过Play中的Anorm) [英] Scala: how to make a Hash(Trie)Map from a Map (via Anorm in Play)

查看:149
本文介绍了Scala:如何从地图制作Hash(Trie)Map(通过Play中的Anorm)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

已在 docs.scala-上的> HashTrieMaps lang.org :

Having read this quote on HashTrieMaps on docs.scala-lang.org:

例如,要在地图上找到给定的键,首先要获取键的哈希码.然后,使用哈希码的最低5位选择第一个子树,然后选择接下来的5位,依此类推.一旦节点中存储的所有元素的哈希码在选择到该级别的位上彼此不同,选择就会停止.

For instance, to find a given key in a map, one first takes the hash code of the key. Then, the lowest 5 bits of the hash code are used to select the first subtree, followed by the next 5 bits and so on. The selection stops once all elements stored in a node have hash codes that differ from each other in the bits that are selected up to this level.

我认为这是一个很棒的(快速阅读!)收藏品,用于存储Map [String,Long].

I figured that be a great (read: fast!) collection to store my Map[String, Long] in.

在我的Play框架(使用Scala)中,我有一段使用Anorm的代码,可加载大约18k的元素.加载需要几秒钟的时间(没什么大不了,但是有什么提示吗?).我想将其保存在内存中",以便快速查找字符串到长的翻译.

In my Play Framework (using Scala) I have this piece of code using Anorm that loads in around 18k of elements. It takes a few seconds to load (no big deal, but any tips?). I'd like to have it 'in memory' for fast look ups for string to long translation.

val data = DB.withConnection { implicit c ⇒
  SQL( "SELECT stringType, longType FROM table ORDER BY stringType;" )
    .as( get[String]( "stringType" ) ~ get[Long]( "longType " )
    map { case ( s ~ l ) ⇒ s -> l }* ).toMap.withDefaultValue( -1L )
}

此代码使data的类型为class scala.collection.immutable.Map$WithDefault.我希望它的类型为HashTrieMap(或HashMap,据我所知,所有Scala HashMaps的链接引用都属于HashTrieMap?).奇怪的是,我找不到如何将其转换为HashTrieMap的方法. (我是Scala,Play和Anorm的新手.)

This code makes data of type class scala.collection.immutable.Map$WithDefault. I'd like this to be of type HashTrieMap (or HashMap, as I understand the linked quote all Scala HashMaps are of HashTrieMap?). Weirdly enough I found no way on how to convert it to a HashTrieMap. (I'm new to Scala, Play and Anorm.)

// Test for the repl (2.9.1.final). Map[String, Long]:
val data = Map( "Hello" -> 1L, "world" -> 2L ).withDefaultValue ( -1L )
data: scala.collection.immutable.Map[java.lang.String,Long] =
  Map(Hello -> 1, world -> 2)

// Google showed me this, but it is still a Map[String, Long].
val hm = scala.collection.immutable.HashMap( data.toArray: _* ).withDefaultValue( -1L )

// This generates an error.
val htm = scala.collection.immutable.HashTrieMap( data.toArray: _* ).withDefaultValue( -1L )

所以我的问题是如何将MapWithDefault转换为HashTrieMap(如果共享HashTrieMap的实现,则转换为HashMap)?

So my question is how to convert the MapWithDefault to HashTrieMap (or HashMap if that shares the implementation of HashTrieMap)?

欢迎任何反馈.

推荐答案

正如您所指向的文档所述,不可变映射已经在引擎盖下实现为HashTrieMap.您可以在REPL中轻松地对此进行验证:

As the documentation that you pointed to explains, immutable maps already are implemented under the hood as HashTrieMaps. You can easily verify this in the REPL:

scala> println( Map(1->"one", 2->"two", 3->"three", 4->"four", 5->"five").getClass )
class scala.collection.immutable.HashMap$HashTrieMap

因此,您没有什么特别的事情要做,您的代码已经在使用HashMap.HashTrieMap了,甚至没有意识到.

So you have nothing special to do, your code already is using HashMap.HashTrieMap without you even realizing.

更准确地说,immutable.Map的默认实现是immutable.HashMap,由immutable.HashMap.HashTrieMap进一步完善(扩展). 请注意,虽然小的不可变映射不是immutable.HashMap.HashTrieMap不是实例,但是是作为特殊情况实现的(这是一种优化).在将它们开始加为immutable.HashMap.HashTrieMap时,存在一定的大小阈值. 例如,在REPL中输入以下内容:

More precisely, the default implementation of immutable.Map is immutable.HashMap, which is further refined (extended) by immutable.HashMap.HashTrieMap. Note though that small immutable maps are not instances of immutable.HashMap.HashTrieMap, but are implemented as special cases (this is an optimization). There is a certain size threshold where they start being impelmented as immutable.HashMap.HashTrieMap. As an example, entering the following in the REPL:

val m0 = HashMap[Int,String]()
val m1 = m0 + (1 -> "one")
val m2 = m1 + (2 -> "two")
val m3 = m2 + (3 -> "three")
println(s"m0: ${m0.getClass.getSimpleName}, m1: ${m1.getClass.getSimpleName}, m2: ${m2.getClass.getSimpleName}, m3: ${m3.getClass.getSimpleName}")

将打印以下内容:

m0: EmptyHashMap$, m1: HashMap1, m2: HashTrieMap, m3: HashTrieMap

因此,这里的空映射是EmptyHashMap$的一个实例.向其添加元素将得到HashMap1,最后再添加另一个元素将得到HashTrieMap.

So here the empty map is an instance of EmptyHashMap$. Adding an element to that gives a HashMap1, and adding yet another element finally gives a HashTrieMap.

最后,withDefaultValue的使用不会改变任何内容,因为withDefaultValue只会返回一个实例Map.WithDefault,该实例将包裹初始映射(仍将是HashMap.HashTrieMap).

Finally, the use of withDefaultValue does not change anything, as withDefaultValue will just return an instance Map.WithDefault wich wraps the initial map (which will still be a HashMap.HashTrieMap).

这篇关于Scala:如何从地图制作Hash(Trie)Map(通过Play中的Anorm)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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