Java - 数百万条记录,HashMap 抛出 OutOfMemoryError

标签 java hashmap out-of-memory

我正在读取一个文件,以将每条记录的几个字段解析为引用键,将另一个字段解析为引用值。这些键和值被另一个进程引用。 因此,我选择了一个 HashMap,这样我就可以轻松地获取每个键的值。

但是,每个文件都包含数千万条记录。因此,HashMap 会抛出 OutOfMemoryError。如果将来的输入文件增长,我希望增加堆内存不是一个好的解决方案。

对于SO中的类似问题,大多数建议使用数据库。我担心我不会选择使用数据库。有没有其他方法可以解决这个问题?

编辑:我需要为 4 个这样的文件执行类似的 HashMap 加载 :( 我需要所有四个文件。Bcoz,如果我在第一个 Map 中找不到与我的输入匹配的条目,我需要在第二个中找到,然后如果没有,那么第三,最后是第四。

编辑 2:我总结的文件大约有 1 GB。 编辑 3:

034560000010000001750                                  
000234500010000100752                            
012340000010000300374

我在文件中有这样的记录。我需要将 03456000001000000 作为键,将 1750 作为值。对于所有数百万条记录。我将引用这些键并为我的另一个进程获取值。

最佳答案

使用数据库本身不会减少内存成本或运行时间。

但是,默认的散列图可能不是您要查找的内容,具体取决于您的数据类型。与 Integer 等原始值一起使用时s 然后 java hashmaps 有一个大量内存开销。在 HashMap<Integer, Integer> ,每个条目使用 24+16+16 个字节。未使用的条目(并且 hashmap 保留了一半未使用的条目)额外占用 4 个字节。因此,您可以粗略估计 Java 中每个 int->int 条目 >56 字节 HashMap<Integer, Integer> .

如果将整数编码为 String ,我们说的可能是 6 位数字,这可能是底层 char[] 的 24 个字节。数组(16 位字符;数组的开销为 12 字节,大小是 8 的倍数!),加上 String 的 16 字节周围的物体(也可能是 24 个)。对于每个键和值。所以大约是 24+40+40,即每个条目超过 104 个字节。 (更新:由于您的 key 长度为 17 个字符,因此将其设为 24+62+40,即 136 字节)

如果您使用原始 HashMap ,例如 GNU Trove TIntIntHashMap ,它只需要 8 个字节 + 未使用,所以让我们估计每个条目 16 个字节,内存至少减少 6 倍。 (更新:对于 TLongIntHashMap,估计每个条目 12 个字节,24 个字节加上未使用的桶的开销。)

现在您还可以将所有内容存储在一个庞大的排序列表中。这将允许您执行快速加入 操作,并且您将损失大量未使用条目的开销,并且可能可以在更短的时间内处理两倍的数量。

哦,如果您知道有效值范围,您可以将数组滥用为“hashmap”

即如果您的有效 key 是 0...999999,则只需使用 int[1000000]作为存储,并将每个条目写入适当的行。根本不存储 key - 它是数组中的偏移量。

最后但同样重要的是,默认情况下,Java 仅使用 25% 的内存。您可能想增加其内存限制。

关于Java - 数百万条记录,HashMap 抛出 OutOfMemoryError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27600812/

相关文章:

Java映射序列

java - 当 Tomcat 运行 OutOfMemory 时获取堆转储

java - 数据库多表和 ICS

java - 仅在必要时绘制后如何缩放 Image/Graphics2d

java - Servlet 中的意外异常行为

android - 如何减小透明位图大小(不是尺寸)

c - 循环插入二叉树

java - 让一个线程启动另一个线程然后死掉

java - 操作复杂的 HashMap

java - 为什么我不能在 Java 中创建具有 'long' 类型的 HashMap?