开销与代码速度(java.io.File 数组与 java.lang.String 数组)

Posted

技术标签:

【中文标题】开销与代码速度(java.io.File 数组与 java.lang.String 数组)【英文标题】:Overhead vs. Speed of Code (java.io.File array vs. java.lang.String array) 【发布时间】:2011-08-22 14:29:16 【问题描述】:

只是想解决我在这里遇到的一个小问题。

目前,我正在开发一个应用程序,该应用程序涉及将文件列表收集到内存中,以便删除。现在,在这一点上,我认为 java.io.File 数组可能会占用太多内存,因为此上下文中的文件列表可能有数百个可能的条目。

我认为收集文件名列表并将它们存储为 java.lang.String 会更节省内存,而不是用 File 对象列表消耗过多的内存。现在,这是我的问题:考虑到要删除这些文件的目标,其中哪些会更便宜:

    存储文件对象数组而不是字符串对象,并调用 .delete();循环中的每一个(使用的内存过多)。 使用文件名存储字符串对象数组,但对于循环的每次迭代,使用文件名列表创建一个新的文件对象,然后调用 .delete();在该文件上(这意味着每次循环迭代时,都会创建和销毁一个新的 File 对象——可能使用了过多的处理器能力)。

我想让程序尽可能快,所以任何一种方法都有其优点,我只想看看哪一种方法的开销最小。提前致谢!

【问题讨论】:

你都试过了吗?哪个更快?这是一个理论上很难回答的问题。 过早优化是万恶之源 你确认File数组占用太多内存了吗?当然,Java 的File 对象的大小大于零,但它们只是对文件系统位置的引用。它们不会将文件内容隐式传输到您的程序中。 @Kevin:适当强调过早的;在较弱的 Droids 上,这可能实际上是相关的(不确定这是否真的是 ,OP 没有在那里共享足够的上下文)。 使用File 数组,除非部署后的基准测试表明该方法存在问题。谢谢。 【参考方案1】:

java.io.File 代表文件系统中条目的文件名信息/元数据,它不包含文件的内容。

换句话说,像new File("somelarge.txt") 这样的代码不会将somelarge.txt 文件加载到内存中。

每个 File 对象包含的唯一真实数据是 File 的 String path(以及 transient int prefixLength) - 考虑 File 类只是 String path 的包装器,它知道如何调用所有文件系统操作。

这里的最佳选择是最容易阅读并最好地传达您的意图的代码,除非有一些其他要求。

【讨论】:

+1:File 包含 Stringint,因此内存占用应该不是问题。追求可读性。【参考方案2】:

我不想粗鲁,但让我从调用“不惜一切代价避免过早优化”的口头禅开始。你的代码性能敏感吗?你有内存使用限制吗?循环中的数百个 File 对象或数百个 File 对象创建听起来都不是那么糟糕。不过,如果您真的想进行优化,请使用 Profiler 并使用这两种策略运行一些基准测试。我个人会推荐Netbeans Profiler。

【讨论】:

【参考方案3】:

现在,在这一点上,我认为 java.io.File 数组可能需要 占用太多内存,因为列表 此上下文中的文件可能位于 数百个可能的条目。

除非您使用的是严重资源匮乏的系统,否则您不会遇到您认为的问题。

请记住,Java File 对象只是“文件和目录路径名的抽象表示”。因此,它代表任何文件的固定内存成本,无论文件有多大。如果您只处理数百个文件,那么您几乎可以肯定不会达到堆空间的任何限制。

如果您创建一个解决方案并发现您在使用分析和监控时面临内存限制,那么此实现是您应该关注的最后一个地方之一。根本就没有那么多内存。

因此,简而言之,您应该编写自己最了解并且将来能够维护的代码。简单的代码是你的朋友。

【讨论】:

【参考方案4】:

文件在很大程度上是一个字符串的包装器,它比字符串本身多消耗 32 个字节。如果您在内存成本约为 70 美元/GB 的服务器中有 1000 个这样的内存,那么它消耗的额外内存价值约为 0.22 美分。如果您领取最低工资,这大约相当于您的 1 秒时间。

除非您的设备内存有限,否则您可能无需担心任何消耗小于 1 MB 的内容。

【讨论】:

【参考方案5】:

对我来说听起来像是过早的优化,除非

    您正在使用资源受限的移动设备,或者 数组中的元素(文件路径)数量可能非常大。

话虽如此,String 对象数组在内存和速度方面胜过 File 对象数组。这有几个原因:

    一个文件对象有许多私有属性,包括但不限于

    私有字符串字段属性

    transient 文件系统特定前缀的前缀长度字段

    File 对象实例化依赖于对 java.io.FileSystem 的具体实现的静态引用,File 构造函数对其进行调用

    至少,构建 File 对象需要调用 FileSystem.normalize() 和 FileSystem.prefixLength()(除了实例化它自己对路径和前缀长度的私有引用。

因此,创建 n 个文件实例数组的成本等于

n * (expense_of_constructor + avg_construction_of_individual_path_strings_off_filesystem)

expense_of_constructor = init_of_local_vars + expense_of_path_normalization + expense_of_prefix_length_computation

使用 n 个字符串路径名数组,成本只是

 n * (avg_construction_of_individual_path_strings_off_filesystem)

就空间而言,n 个文件对象数组的内存占用将是:

 n * (avg_string_path_size + 32_bits_of_prefix_length + size_of_File_object_itself)

n 个字符串对象的数组将是

 n * avg_string_path_size

为了简单和方便,我会使用一个字符串数组。我什至都懒得做任何估计。大多数时候,更简单往往更好。只有当您使用非常受限的设备(例如手机)时,这个细节才有意义。

【讨论】:

尽管如此删除一个文件,你将创建一个File对象n次。 更正:要删除 a 文件,请创建 1 文件对象。要删除 n 文件,请创建 n 文件对象。我们是想一次创建 n 个 File 对象,还是在删除时一次只创建一个?是的,确实我们必须创建 n 个 File 对象,但是在一次将它们放在一个数组中和以交错的、基于需要的方式这样做之间有很大的不同。通常,您只在需要时创建资源。 是的,这是真的。 n File 对象数组比 n String 对象数组占用更多内存。

以上是关于开销与代码速度(java.io.File 数组与 java.lang.String 数组)的主要内容,如果未能解决你的问题,请参考以下文章

java.io.File中的pathSeparator与separator的差异

java中图像与数组转换

java.IO.File中与系统相关的静态字段如:“/”

java.io.File类

Java基础——IO流

push 与 mov 的成本(堆栈与近内存)以及函数调用的开销