Java 如何在大单词表(词汇表)中查找一个具有下降内存消耗和查找时间的单词? 问题

Java 如何在大单词表(词汇表)中查找一个具有下降内存消耗和查找时间的单词? 问题,java,android,performance,memory,Java,Android,Performance,Memory,[以下是应用程序在哪些约束条件下应执行的操作的说明] 我想要一个数据结构,它可以搜索250000字列表中是否存在字符串,同时只使用相当数量的ram,并保持将此数据结构加载到ram中所需的时间很短(比如0-8秒)。查找单词所需的时间也应该很快(比如0到0.5秒),但ram的使用更为重要。它还可以创建多个游戏(更多关于这个游戏的内容,请参阅标题“使用”),而不需要更多的内存 知道哪些单词以字符串开头也是非常有价值的,但这还不足以牺牲几秒钟的加载时间 使用 这是一款Android离线游戏。有限的内存

[以下是应用程序在哪些约束条件下应执行的操作的说明]

我想要一个数据结构,它可以搜索250000字列表中是否存在
字符串
,同时只使用相当数量的ram,并保持将此数据结构加载到ram中所需的时间很短(比如0-8秒)。查找单词所需的时间也应该很快(比如0到0.5秒),但ram的使用更为重要。它还可以创建多个游戏(更多关于这个游戏的内容,请参阅标题“使用”),而不需要更多的内存

知道哪些单词以
字符串开头也是非常有价值的,但这还不足以牺牲几秒钟的加载时间


使用 这是一款Android离线游戏。有限的内存可用。我的空Android应用程序已经使用了大约17mb(在Android Studio中使用内存监视器)。我的android设备将ram的使用限制在26mb,为我的整个
活动留下了大约8mb的可用空间


我试过的选择 它们似乎都是以不同的方式注定的

  • 哈希映射-将所有单词读入哈希映射对象

    1.1初始化速度:以23秒的速度将每个单词读入哈希映射

    1.2内存使用情况:使用了大量内存,但我忘记了具体使用了多少

    1.3搜索速度:查找列表中是否存在单词当然很快

    1.4缩小可能的单词范围(可选):速度慢,需要遍历整个哈希映射并逐个删除。另外,因为它使用删除,所以无法使用同一个哈希映射实例玩多个游戏。添加更多游戏时会占用太多内存,因此无法缩小可能的单词范围

  • &

    2.1初始化速度:以47秒的速度将每个单词读入RadixTree

    2.2内存使用情况:使用了大量内存,以至于Android暂停了几次线程

    2.3搜索速度:快速查找列表中是否存在单词

    2.4缩小可能单词的范围(可选):速度极快,因为只需引用树中的节点即可找到所有可能单词作为其子级。你可以玩很多游戏来缩小可能的单词范围,因为额外的游戏只需要引用树中的一个节点

  • 扫描仪-按顺序浏览word文件

    3.1初始化速度:

    3.2内存使用:

    3.3搜索速度:约20秒

    3.4缩小可能的词语范围(可选):无法现实地完成

  • 简单代码:

    String word;
    String wordToFind = "example";
    boolean foundWord = false;
    
    while (wordFile.hasNextLine()) {
        word = wordFile.nextLine();
        if(word.equals(wordToFind)) {
            foundWord = true;
            break;
        }
    }
    
    test.close();
    

    我想到的选择:
  • 1.1初始化速度:可能与哈希映射相同,或稍短,约20秒。不过,我希望调用Array.sort()不会花费太多时间,目前还不知道

    1.2ram用法:如果您仅使用26个字母的字母表来表示12个字母或以下的单词,则需要5位(2^5=32)来编码字符串。一个long数组需要250000*8位=大约2mb。这并不过分

    1.3搜索速度:数组。二进制搜索()

    1.4缩小可能单词的范围(可选):缩小可能单词的范围是可能的,但我不确定如何

  • 带存储的Hashmap-创建一个hashfunction,将单词映射到单词列表文件的索引号。然后在这个特定位置访问文件,并从这里查看是否存在单词。您可以利用字母表的顺序来确定是否仍然可以找到该单词,因为单词列表是按自然顺序排列的

    2.1初始化速度:不需要(因为我需要事先将每个单词放在正确的索引中。)

    2.2内存使用:

    2.3搜索速度:快速

    2.4缩小可能的单词范围(可选):不可能


  • 我有一些具体问题
  • 我在“我想到的选项”一节中想到的选项是可行的选项,还是我错过了一些使它们无法实施的事情
  • 是否有我没有想到的性能更好/相等的选项
  • 结束语 我已经被困在这大约一个星期了。因此,任何新想法都是非常受欢迎的。如果我上面的任何假设是错误的,我也很高兴听到他们


    我这样写这篇文章,是为了让其他人也能从中吸取教训,要么看看我的错误,要么看看答案中有什么有用的地方。

    这听起来像是一个很好的例子。如果你愿意冒被错误地认为是单词的风险,你可以将你的单词表压缩成一个你愿意做的大小都可以的内存量。

    我也遇到过同样的问题,最终选择了“磁盘上”的trie。也就是说,我使用字节偏移量而不是指针将数据结构编码到单个文件中(按相反顺序打包节点,最后写入的是“根”节点)

    只需将文件读入字节数组即可快速加载,trie遍历使用的偏移量值与指针相同


    我的200K单词集可容纳1.7 MB(未压缩),每个单词终止节点中有一个4字节的值。

    为什么不使用SQLite数据库呢?“根据这个帖子,应用程序可以使用的最大RAM量取决于设备的16-32兆位RAM”——您可能希望考虑阅读关于这个问题的已接受答案。“我的