我有一个包含数百万个条目的大型hashmap,我想将它保存到磁盘,这样当它再次从磁盘读取时,我没有将键值对重新插入到磁盘中的开销。再次映射。
我正在尝试使用谷物库来执行此操作,但似乎HashMap数据类型需要派生Generic。有没有办法做到这一点?
答案 0 :(得分:5)
您可以使用stand-alone deriving为Generic
生成自己的HashMap
个实例。您可能会收到有关orphan instances的警告,但您也可能不在乎:)无论如何,我没有尝试过这个,但它可能值得一试......
答案 1 :(得分:1)
我不确定使用Generics是否是实现高性能的最佳选择。我最好的选择实际上是为Serializable编写自己的实例,如下所示:
instance (Serializable a) => Serializable (HashMap a) where
...
为避免创建孤立实例,您可以使用newtype trick:
newtype SerializableHashMap a = SerializableHashMap { toHashMap :: HashMap a }
instance (Serializable a) => SerializableHashMap a where
...
问题是如何定义...
?
在您真正尝试实施和对可能的解决方案进行基准测试之前,没有明确的答案。
一种可能的解决方案是使用toList
/ fromList
函数并存储/读取HashMap
的大小。
另一个(类似于使用Generics)将基于内部HashMap结构编写直接序列化。鉴于您实际上没有导出的内部结构,这只是Generics的工作。
答案 2 :(得分:0)
目前,如果不修改HashMap库本身,就无法使HashMap可序列化。
使用@ mergeconflict的答案所描述的独立派生,不可能使Data.HashMap成为Generic的实例(用于谷物),因为Data.HashMap不会导出其所有构造函数(这是一个要求GHC)。
因此,序列化HashMap的唯一解决方案似乎是使用toList / fromList接口。
答案 3 :(得分:0)
如果你可以使用二进制文件,那就是二元孤儿,它为无序容器提供实例。由于一些影响冲突,我无法安装二元孤儿,但只是抓住了我需要的部分,例如:
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveGeneric #-}
module Bin where
import Data.Binary
import Data.ByteString.Lazy.Internal
import Data.Hashable (Hashable)
import qualified Data.HashMap.Strict as M
import qualified Data.Text as T
#if !(MIN_VERSION_text(1,2,1))
import Data.Text.Binary ()
#endif
instance (Hashable k, Eq k, Binary k, Binary v) => Binary (M.HashMap k v) where
get = fmap M.fromList get
put = put . M.toList
-- Note: plain `encode M.fromList []` without type annotations won't work
encodeModel :: M.HashMap T.Text Int -> ByteString
encodeModel m =
encode m
答案 4 :(得分:-1)
CerealPlus包提供严格HashMaps的Serialize定义。