java是一个高效的大型单词数组
我正在寻找一个Java数据结构来存储一个大文本(大约一百万个单词),这样我就可以按索引获取一个单词(例如,获取531467个单词)
String[]或ArrayList的问题是它们占用了太多内存—在我的环境中,每个字大约40字节
我曾想过使用一个字符串[],其中每个元素是由10个单词组成的一块,由一个空格连接。这是更有效的内存-约20字节每字;但访问速度要慢得多
有没有更有效的方法来解决这个问题
你可以在下面搜索框中键入要查询的问题!
我正在寻找一个Java数据结构来存储一个大文本(大约一百万个单词),这样我就可以按索引获取一个单词(例如,获取531467个单词)
String[]或ArrayList的问题是它们占用了太多内存—在我的环境中,每个字大约40字节
我曾想过使用一个字符串[],其中每个元素是由10个单词组成的一块,由一个空格连接。这是更有效的内存-约20字节每字;但访问速度要慢得多
有没有更有效的方法来解决这个问题
# 1 楼答案
正如Jon Skeet已经提到的,40mb并不是太大
但是您声明您正在存储一个文本,因此可能有许多相同的字符串。 例如,停止像“and”和“or”这样的单词
你可以使用字符串。实习生()[1]。这将汇集字符串并返回对已存在字符串的引用
intern()相当慢,因此您可以用一个HashMap替换它,该HashMap将为您执行相同的操作
[1]http://download.oracle.com/javase/6/docs/api/java/lang/String.html#intern%28%29
# 2 楼答案
一种选择是使用UTF-8编码的文本存储字节数组:
然后:
这将在两个方面变得更小:
但我并不推荐这种方法。。。同样,它的访问速度较慢,因为每次都需要创建一个新的
String
。从根本上说,如果你需要一百万个字符串对象(因此你不想每次都支付娱乐罚款),那么你将不得不为一百万个字符串对象使用内存# 3 楼答案
您可以创建如下数据结构:
List<string> wordlist
Dictionary<string, int> tsildrow // for reverse lookup while building the structure
List<int> wordindex
wordlist
将包含所有(唯一)单词的列表,tsildrow
将给出wordlist
中某个单词的索引,wordindex
将告诉您文本中某个特定索引的wordlist
索引您可以按以下方式操作它:
这将填充您的数据结构。现在,要查找索引531467中的单词:
您可以如下方式复制整个文本:
除了,你仍然会有标点等问题
如果您不想再添加任何单词(即您的文本是稳定的),您可以删除
tsildrow
以释放一些内存(如果这是您的问题)# 4 楼答案
http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html
似乎是一篇有趣的文章: http://www.javamex.com/tutorials/memory/string_saving_memory.shtml
我听说绳子在存储大字符串的速度方面非常好,尽管不能确定它的记忆能力。但你可能想看看。 http://ahmadsoft.org/ropes/ http://en.wikipedia.org/wiki/Rope_%28computer_science%29
# 5 楼答案
您可以考虑使用memory mapping the data structure,但性能可能会非常糟糕
# 6 楼答案
将所有单词存储在单个字符串中:
除了它们包含的字符外,使用此解决方案(在
indices
中的条目)每个单词都有四个字节的开销。检索带有wordAt
的单词将始终分配一个新字符串;您可以通过保存StringBuilder
的toString()
而不是构建器本身来避免这种情况,尽管它在构造时使用了更多内存根据文本、语言等的类型,您可能需要更好地处理重复出现的单词的解决方案(如the one previously proposed)