【问题标题】:Use arrays, lists, or else for thousands of strings?使用数组、列表或其他数千个字符串?
【发布时间】:2012-11-02 14:16:50
【问题描述】:

我有以下获取目录名称的方法:

    private List<String> getListOfDirectories(String rootDirectoryPath) {

        List<String> listOfDirectories = new ArrayList<>();

        File directory = new File(rootDirectoryPath);
        File[] listOfFiles = directory.listFiles();

        for (int i = 0; i < listOfFiles.length; i++) {

            if (listOfFiles[i].isDirectory()) {
                listOfDirectories.add(listOfFiles[i].getName());
            }
        }

        return listOfDirectories;
    }

我暂时将这些目录名称存储在列表中(不确定存储是否是正确的术语)。如果有 50000 个目录名,List 是正确的选择吗?它的内存效率高吗?它可以处理 50000 或更多的字符串吗?

编辑:我正在开发一个在本地目录中搜索 html 文件并解析这些 html 文件的应用程序。

【问题讨论】:

  • 无论你怎么剪,你的程序都将存储 50,000 个字符串。重要的是您将如何处理这些字符串。大量随机访问?搜索列表?添加/删除元素?这些问题将帮助您选择正确的数据结构。
  • 一个ArrayList是特殊动态array。我唯一可能建议的是您为构造提供初始容量或调用ensureCapacity。这将使列表更有效地增长。基本上。 ArrayList 将在没有足够空间容纳新元素的情况下将列表增加一个元素。这结束了调用Arrays.copy 将内容从旧的支持数组移动到新的数组,这可能会变得低效(更糟糕的情况,你将有两个数组,一个有 49、999 个元素,一个有 50、000 个元素在内存中一下子……
  • @MadProgrammer 数组的大小通常是 加倍,所以最坏的情况实际上是 2 个数组,一个有 49,999 个元素,一个有两倍, 99998(当然,实际数组大小将是 2 的幂 :)
  • 我正在构建一个从本地目录获取所有 html 文件并解析这些 html 文件的应用程序。
  • @MattBall 实际上(在阅读了更多代码之后),它更像是 74999 ((49999 * 3) / 2 + 1) - 不用说,更好地确保之前的容量你开始;)

标签: java arrays string list


【解决方案1】:

ArrayList&lt;String&gt; 在内存使用方面接近于裸String[]。如果您知道要存储大约 50,000 个字符串,那么使用该初始容量构建 ArrayList 会有所帮助;它将大大减少重新分配。但是,我绝对不会使用LinkedList。这需要更多的开销。

只要字符串本身适合内存,存储 50,000 个条目就没有问题。

【讨论】:

    【解决方案2】:

    List 只是一个接口,所以它真的取决于列表的实现。假设ArrayList&lt;String&gt;,它的内存效率大致与String[] 一样。数组列表的最坏情况是底层数组是一个常数因子(通常为 2),大于它实际存储的数据量。

    如果您需要内存效率,具体取决于您稍后使用列表的方式,您可以使用trieBloom filter 之类的东西。

    【讨论】:

    • IIRC,常数因子实际上是 1.5x。也就是说——Strings 本身的内存使用量几乎肯定会超过您存储它们的列表。
    • 这不是一个常数因子...它是一个平均因子...它假设您一开始并没有大量过度分配。
    【解决方案3】:

    列表可以处理它,它只取决于是否有那么多可用的内存。

    如果你真的知道你将拥有 50000 个元素,那么最好将列表声明如下

    List<String> list = new ArrayList<String>(50000); //specify the initial capacity
    

    这将消除列表调整开销。

    【讨论】:

    • 我认为您的意思是“消除”而不是“元素”。 (尽管您可能还指的是“大象”:-~ :-))
    • 是的,这就是我要写的,但我不知道我是如何在那里获得元素的。 :) 谢谢。
    【解决方案4】:

    正如你所指出的;您正在寻找在本地目录中搜索 html 文件的有效方法。

    所以我认为在 ArrayList 中存储内存中的所有细节是没有意义的,因为 html 文件的数量会不断变化。我建议你应该运行一个搜索所有这些文件的进程,并将 html 文件名存储在一个单独的物理文件中(比如一个 txt 文件)。这样,您可以通过运行作业定期更新文件列表(您可以拥有 unix 脚本,甚至可以通过 java 来完成)。

    当你真正需要对那些 html 文件执行一些操作时;从 txt 文件中读取 html 文件名。

    从 txt 文件读取后,您可以使用 ArrayList;但不建议将所有名称都保存在内存中。

    【讨论】:

      猜你喜欢
      • 2021-12-18
      • 1970-01-01
      • 1970-01-01
      • 2014-07-04
      • 1970-01-01
      • 2010-12-18
      • 2011-08-20
      • 2016-09-05
      • 1970-01-01
      相关资源
      最近更新 更多