在下面的代码中,哪种情况(1或2)更“高效”?
static final String NEWLINE = System.getProperty("line.separator");
Vector<String> text_vec = ...;
FileWriter file_writer = new FileWriter(path);
BufferedWriter buffered_writer = new BufferedWriter(file_writer);
try {
for (String text: text_vec) {
// Case 1: String concatenation
buffered_writer.write(text + NEWLINE);
// Case 2: Extra call to write()
buffered_writer.write(text);
buffered_writer.write(NEWLINE);
}
}
finally {
buffered_writer.close();
}
如果是#1,据我所知,字符串连接由Java编译器通过自动分配StringBuilder对象来处理。由于String值在编译时是未知的,因此无法在“早期”(在编译期间)连接。
所以问题是:哪一个更有效(CPU /内存/挂钟时间)?
我将“有效”的确切定义留给那些回答的人。我不是Java虚拟机的专家。
答案 0 :(得分:3)
除非你对它进行基准测试并证明你有充分的理由不,否则你应该直接写入缓冲区。它是提供一种有效的文件写入方法。
此外,不要忘记在写入缓冲区时刷新缓冲区。
答案 1 :(得分:1)
第二个应该更快,因为它阻止无用的String对象创建,这是因为BufferedWriter写入直接将其输入转换为字节/字符,而不是创建无用的字符串对象。
案例1:
您的代码:
1 time StringBuilder;
(通过将字符串附加在一起暗示)
1 time String;
(通过将字符串附加在一起暗示)
1 time char[];
由缓冲的作家
案例2:
您的代码:
2 time char[];
由缓冲的作家
由于最后一个案例产生的对象较少,对象较少,因此这应该更快。
答案 2 :(得分:0)
文件IO比使用JVM中的字符串连接所做的任何操作都要慢几个数量级。无论如何,磁盘都将成为你的瓶颈。
这假设我们不是在谈论SSD,它可能仍然比JVM本身慢。
编辑:显然根据评论没有很好地沟通。 Lemme尝试放大文本框。 OP表示FileWriter。这意味着最终所有数据都必须转到磁盘。磁盘延迟以毫秒为单位,吞吐量以兆字节/秒为单位,通常为10秒,但不是100秒。
内存延迟以纳秒为单位,吞吐量以千兆字节每秒为单位。你的大多数字符串连接发生在那里。这比磁盘快3-6个数量级。
无论您如何缓冲,连接等,最终都会遇到磁盘的吞吐量限制。最重要的是如果你冲洗()并等待它真正完成冲洗到媒体。
缓冲并不意味着蹲下而不是使磁盘IO更有效。是的,你应该在写作时使用缓冲区,大约1k-16k的顺序就足够了。但是,该缓冲区不会更改磁盘的吞吐量。这比字符串连接问题慢几个数量级。
因此。如果您想在写入磁盘时谈论效率,请忘掉如何连接字符串。只需轻松阅读代码即可。
答案 3 :(得分:0)
这一切都通过一个缓冲区,所以应该没什么区别。可能版本2的额外写入速度更快。
但除非你这么多次这样做,否则不重要。