使用Java我想创建一个可以增长和增长的Map,并且可能大于可用内存的大小。现在显然使用标准的POJO HashMap,我们将耗尽内存并且JVM将崩溃。所以我一直在想着如果它意识到内存不足,它可以将当前内容写入磁盘。
有没有人实施过这样的事情或知道现有的任何解决方案?
我要做的是一次读取一个非常大的ASCII文件(比如50Gb)。每行包含一个键和一个值。密钥可以在文件中复制。然后,我将每一行存储在一个Map中,这是一个值列表的键。这张地图是将会成长和成长的对象。
任何建议都非常感谢。
菲尔
更新
感谢所有人的意见和建议。由于我描述的问题,数据库是正确的,可扩展的解决方案。我应该说这是一个临时Map,需要在短时间内创建和使用,以帮助解析文件。在这种情况下,迈克尔建议“仅存储行号而不是实际值”是最合适的。将迈克尔的答案标记为推荐的解决方案。
答案 0 :(得分:13)
我认为您正在寻找数据库。
答案 1 :(得分:3)
NoSQL数据库可能很容易设置,它更像是一张地图。 现在从Oracle查看BerkeleyDB Java版。 它有一个类似界面的地图,可以嵌入,因此不需要复杂的设置
答案 2 :(得分:2)
听起来像是把你的大文件转储到DB中。
嗯,我有同样的情况。但是,在我的情况下,一切都是TXT
文件格式,整个文件都有相同的格式化行。所以,我所做的就是将文件分成几个部分(可能是我的JVM可以处理的最大尺寸)。然后我逐个调用文件,以便进行处理。
另一种方法是,您可以直接将数据直接加载到数据库中。
答案 3 :(得分:2)
说真的,按照建议选择一个简单的数据库。这不是开销 - 您不必使用JPA或其他东西,只需使用原生SQL的普通JDBC。例如,Derby或HSQL可以在嵌入模式下运行,无需定义用户,访问权限,单独启动服务器。
当你深入到哈希映射解决方案中时,“开销”会刺伤你,结果是你需要另一个优化来避免OutOfMemoryException,或者文件不是50 GB,而是75。 ..真的,不要去那里。
答案 4 :(得分:0)
如果您只是想构建用于数据处理的地图(而不是随机访问以响应请求),那么MapReduce可能就是您想要的,而无需使用数据库。< / p>
编辑:请注意,尽管许多MapReduce引入的重点是运行许多节点的能力,但您仍然可以从避免将所有数据保存在一台机器上的内存中获益。
答案 5 :(得分:0)
你有多少记忆?除非你有足够的内存来保存内存中的大部分数据,否则它可能会失败。重度分页的程序可以慢1000倍或更多。有些PC有16-24 GB,你可能会考虑增加内存。
假设有足够的重复项,您可以将大部分数据保留在内存中。我建议你使用自己制作的基于字节的String类,因为你有ASCII数据并且你将你的值存储为另一个&#34; String&#34; types(带分隔符)您可能会发现可以将工作数据集保存在内存中。
答案 6 :(得分:0)
我使用BerkleyDB,虽然它比Map更复杂(虽然它们有一个Map包装器,除了简单的应用程序之外我不推荐使用它)
http://www.oracle.com/technetwork/database/berkeleydb/overview/index.html
它也可以在Maven http://www.oracle.com/technetwork/database/berkeleydb/downloads/maven-087630.html
中使用 <dependencies>
<dependency>
<groupId>com.sleepycat</groupId>
<artifactId>je</artifactId>
<version>3.3.75</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>oracleReleases</id>
<name>Oracle Released Java Packages</name>
<url>http://download.oracle.com/maven</url>
<layout>default</layout>
</repository>
</repositories>
它还有供应商锁定的另一个缺点(即你被迫使用这个工具。虽然可能有其他Map包装器到其他一些数据库)
所以只需根据您的需要选择。
答案 7 :(得分:0)
大多数缓存API都像地图一样工作,支持溢出到磁盘。例如Ehcache支持。或者按照this tutorial for guave。