我正在创建一个使用字典的Scrabble游戏。为了提高效率,不是将整个字典(通过txt文件)加载到数据结构(Set,List等),而是有任何内置的java类可以帮助我将文件的内容视为String。
具体来说,我想做的是通过做一些像fileName.contains(word)这样简单的事情来检查游戏中的单词是否是字典中的有效单词,而不是使用内存效率低且使用列表的巨大列表。包含(字)。
你们对我能做什么有任何想法吗?如果字典文件必须是txt文件以外的其他内容(例如xml文件),我也可以尝试使用它。
此方法不是Java API的一部分。
HashSet没有想到,我坚持认为所有contains()方法都使用了O(n)时间,感谢Bozho清除它,看起来我将使用HashSet。
答案 0 :(得分:7)
我认为你最好的选择是将它们全部加载到内存中HashSet
。那里contains(word)
是O(1)。
如果您将其记录在内存中,那么将其String
作为contains(..)
进行调用的效率远低于HashSet
。
我必须提到另一个选项 - 有一个数据结构来表示字典 - 它被称为Trie
。但是,您无法在JDK中找到实现。
一个非常粗略的计算表明,使用所有英文单词(100万),您将需要~12兆字节的RAM。这比JVM的默认内存设置少几倍。 (平均100万* 6个字母*每个字母2个字节= 12个百万字节,约为12兆字节)。 (好吧,也许存储哈希值更多)
如果您真的坚持不在内存中阅读它,并且想要扫描文件中的某个单词,那么您可以使用java.util.Scanner
及其scanner.findWithHorizon(..)
。但这样效率很低 - 我假设O(n)和I / O开销。
答案 1 :(得分:3)
虽然HashSet可能是一个完全可以接受的解决方案(参见Bozho的回答),但还有其他数据结构可以使用,包括Trie或Heap。
Trie的优点是,取决于实现细节,可以共享起始前缀字母(毕竟,trie也称为“前缀树”)。根据实施结构和数据,这实际上可能是也可能不是改进。
另一个选项,特别是在需要基于文件的访问时,是使用Heap - Java的PriorityQueue实际上是一个堆,但它不是基于文件的,所以这需要查找/创建一个实现
所有这些数据结构(以及更多)都可以实现为基于文件(使用更多IO 每次查找 - 实际上可能总体上更少 - 但节省内存)或实现直接(例如使用SQLite,让它做它的B-Tree事情)。 SQLite擅长于它可以是一个“常用工具”(曾经常用;-)在工具箱中;数据导入,检查和修改很容易,“它只是工作”。 SQLite甚至可用于功能较弱的系统,例如Android。
HashSet随Java免费提供,但没有标准的Trie或基于文件的Heap实现。我将从HashSet开始 - 推理:
快乐的编码。
随机数据结构实现的链接(可能适用也可能不适用):
HashSet<String>
的内存要求。 (Java中的字符串使用UTF-16编码,该编码至少为两个字节/字符。)答案 2 :(得分:1)
您需要压缩数据以避免存储所有这些字词。这样做的方法是树,其中节点是字母,叶子反映单词的结尾。这样您就不会存储重复数据,例如the there these
,这些单词都具有相同的前缀。
有一种方法可以使此解决方案更加节省内存。 (提示:信件订单)
答案 3 :(得分:-1)
使用java.io.BufferedReader的readline()。返回一个字符串。
String line = new BufferedReader (new FileReader (file) ).readline ();