在 clojure.data.int-map 的贡献库中,INode
实现 Branch
始终在一个长度为 16 的 INode[]
中存储其子节点,尽管很多时候并非所有 16 个子节点位置都会被占用。例如,表示的
(int-map 0 0 1 0)
将用一个包含 INode[]
的分支节点表示,其中 0 位置包含 0->0,1 位置包含 1->0,而数组中的其他 14 个空间是 null
,见下文
这与核心的 hashmap/hashset 实现不同,它使用位图来跟踪数组中哪些位置存在,并在读取时可以看到在要读取的索引右边的位图中有多少位是存在的(设置为 1),这将告诉您压缩数组中的实际索引。
可能值得研究一下,使用位图是否能对 int-map 的性能和内存使用产生积极影响。
还可以进一步压缩,通过结合位图和/或掩码和/或前缀和/或偏移量,因为这些字段足够大,以至于没有使用所有位。例如,掩码(long)始终是 15,15 << 4,15 << 8,15 << 12 等。偏移量(int)始终是 0 ... 60,我想。同样,前缀(long)类似的只存储了一个介于 0...64 长度的位掩码的二进制表示,所以原则上可以压缩很多。在这些因素中,我敢肯定会有一个字段可以存储位掩码的 16 位而不需要添加其他字段。