我正在处理一些包含多个G
对象的生成数据文件(数百兆字节)。我需要随机访问这些对象。我猜,一个可能的实现可能是一个很大的HashTable
. 我的程序是用 Java 编写的,似乎java.util.HashMap
无法处理这个问题(不知何故它非常慢)。任何人都可以推荐随机访问这些对象的解决方案吗?
3 回答
如果 aHashMap
非常慢,那么最可能的两个原因如下:
关键类的
hashCode()
and/orequals(Object)
方法可能非常昂贵。例如,如果您使用数组或集合作为键,则该方法将在您每次调用它时hashCode()
访问每个元素,并且该方法将对相等键执行相同的操作。equals
您的键类可能有一个糟糕的
hashCode()
方法,它为程序使用的大部分(不同)键提供相同的值。发生这种情况时,您会遇到许多键冲突,当哈希表变大时,这可能对性能非常不利。
我建议你先看看这些可能性......在改变你的数据结构之前。
注意:如果“几个 G 对象”意味着数十亿个对象,那么您将无法将文件的内容保存在内存中……除非您在具有 100 GB RAM 的机器上运行此应用程序。我建议你做一些“信封背面”的计算,看看你想做的事情是否可行。
无论您的密钥是什么,请确保您通过hashCode()
. 很多时候 HashMap 性能不佳可归咎于碰撞哈希。当发生碰撞时,HashMap 会为碰撞对象生成一个链表。
最坏的情况是,如果您为所有对象返回相同的哈希,HashMap 本质上会变成一个链表。这是编写哈希函数的一个很好的起点:http ://www.javamex.com/tutorials/collections/hash_function_guidelines.shtml
几百 MB 不能容纳几十亿个对象,除非每个对象都有一点(恕我直言,这不是真正的对象)。
我将如何解决这个问题是使用内存映射文件来映射数据的内容并在另一个内存映射文件中构建您自己的哈希表(这需要您扫描一次数据以构建密钥)
根据数据的布局,值得记住的是,随机访问并不是缓存数据的最有效方式,即缓存加载的 64 字节行(取决于架构),如果您的结构不适合内存,则基于记录表可能更有效。