在我的Java应用程序中,我必须扫描文件系统并以递归方式存储已创建文件的路径,以便进行早期搜索。
我尝试将List / ArrayList和HashMap作为存储结构,但当文件系统包含1.000.000+文件时,内存使用量太多了。
如何在不使用一半RAM(8 GB)的情况下存储和快速检索这些“字符串”?
答案 0 :(得分:1)
在全局散列映射中,您可以存储指向Dir-Objects的指针,而不是将完整路径存储为字符串。
对于您找到的每个目录,创建一个Dir-object。每个Dir-object都有一个指向其父Dir-object及其本地名称的指针。
示例:
<?= ?>
两个子目录只需要存储对父目录的引用加上他们的本地名称“a”或“b”。
请注意,不必须首先找到父对象:扫描文件系统时,应该递归执行此操作或明确使用堆栈。当你创建一个Dir-object(例如/ p)时,你将该对象推送到一个堆栈然后你访问(进入)该目录。在创建/ a和/ b sub-Dirs时,只需查看堆栈顶部即可找到其父级。完成/a/long...path/p/ is a Dir you already found.
/a/long...path/p/a
/a/long...path/p/b are two new Dirs
的全部内容后,弹出Dir-object,将其表示为堆栈。
答案 1 :(得分:1)
您在主存储器中存储大量字符串。无论您使用何种数据结构,它都会占用内存。一种方法可能不是始终存储整个路径,而是将它们存储在分层结构中,例如。将map中的目录名称作为键存储,并将该目录的所有值作为递归值存储在列表中。
答案 2 :(得分:0)
这个问题可以有很多答案。人们可以为您提供各种各样的数据结构,或者可能会要求您增加JVM的硬件内存或堆大小。但我认为问题出在其他地方。
仅使用基本数据结构无法解决此问题。这可能也需要在设计级别进行更改。想想你的需要。您要求的是今天的操作系统甚至是存储大量数据的RDBMS所不需要的巨大空间。
数据结构即服务。(DSAS - 它已经存在,例如redis,但是我可能已经创造了这个术语!)。
在您的应用程序设计中,尝试引入一个组件或服务,如redis,memcached或couchdb,专门用于执行“存储大量数据”,“快速搜索”而非标准套接字或其他高速通信协议(如DBUS)
不要担心此类协议的内部工作。有足够的库/ apis为你做。
答案 3 :(得分:0)
我建议您使用HashSet并将md5 sum存储为路径:
Set<Md5Sum> paths = new HashSet<>();
//for each path
String path = ...
byte[] md5 = messageDigestObject.update(path.getBytes());
path.add(new Md5Sum(md5));
您不能直接使用byte[]
作为哈希集中的键。所以你需要创建简单的帮助类:
class Md5Sum{
//it is more memory effiecient than byte[]
long part1, part2;
//override equals and hashCode methods
//..........
}
关于更新
您需要重新扫描文件系统并重新创建此哈希集对象,或者您可以订阅文件系统事件(请参阅WatchService)。