相当复杂,这可能是一个奇怪的想法,需要相当多的工作,但这是我会尝试:
您已经指出了整个任务的两个单独的子问题:
>对于如此大的集合大小,默认的HashMap实现可能不是最理想的
>你需要存储除字符串以外的东西
地图实现
我建议为Map< String,Long>编写一个高度定制的哈希映射实现.接口.在内部,您不必存储字符串.不幸的是5 ^ 32> 2 ^ 64,所以没有办法将你的整个字符串打包成一个长的,好吧,让我们坚持两个长的钥匙.在向地图实现提供字符串键时(使用位移等),您可以在运行中相当有效地进行字符串到/后长[2]转换.
至于包装值,这里有一些注意事项:
对于键值对,标准散列映射需要有一个N长的数组用于存储桶,其中N是当前容量,当从散列键中找到存储桶时,它需要具有键值对的链接列表解析生成相同哈希码的密钥.对于您的具体情况,您可以尝试以下列方式对其进行优化:
>使用大小为3N的long [],其中N是在连续数组中存储键和值的容量
>在此数组中,在位置3 *(哈希码%N)和3 *(哈希码%N)1处存储密钥的long [2]表示,第一个密钥匹配此桶或唯一一个(在插入,否则为零),在位置3 *(哈希码%N)2处存储相应的计数
>对于所有这些情况,其中不同的键导致相同的哈希码并因此产生相同的桶,您将数据存储在标准HashMap< Long2KeyWrapper,Long>中.我们的想法是保持上面提到的数组的容量(并相应地调整大小)足够大到目前为止该连续数组中的大部分数据而不是后备哈希映射.这将大大减少hashmap的存储开销
>不要在N = 2N次迭代中扩展容量,做出较小的增长步骤,例如10-20%.这将在填充地图时降低性能,但会使您的内存占用受到控制
按键
鉴于不平等5 ^ 32> 2 ^ 64你的想法使用位编码5个字母似乎是我现在能想到的最好的.使用3位并相应地长[2].