Java中的字符串构建性能

Java中的字符串构建性能,java,string,Java,String,我的字符串处理有性能问题。 我有一个日志文件(简单文本文件),我必须对其进行操作,并对文本进行几次更改。 所以程序在一个巨大的字符串中逐行添加。 基本上是这样的 while (not_finished) { // create new stringAdd; stringResult=stringResult + stringAdd + "\n"; } // output to a textArea in window textArea.setText(stringResult

我的字符串处理有性能问题。 我有一个日志文件(简单文本文件),我必须对其进行操作,并对文本进行几次更改。
所以程序在一个巨大的字符串中逐行添加。 基本上是这样的

while (not_finished) { 
   // create new stringAdd; 
   stringResult=stringResult + stringAdd + "\n"; 
} 
// output to a textArea in window
textArea.setText(stringResult);
现在它的性能非常糟糕,所以我升级到了StringBuilder

StringBuilder result= new StringBuilder();    
while (not_finished) { 
// create new stringAdd; 
result.append( stringAdd +"\n"); 
} 
// output to a textArea in window
textArea.setText(result.toString()); 
这要快得多。字符串一旦添加到结果中,将不会更改。 问题不在于超过400000行(一行包含1到70个字符)时的性能

如何提高建筑弦的性能?
你有什么想法吗?

有两件事可以改进。您仍在循环中连接字符串,因此可以尝试:

result.append(stringAdd).append('\n'); 
如果事先知道字符串的大小,则可以最小化内部缓冲区大小调整的次数:

// expecting 30k characters:
StringBuilder result= new StringBuilder(30_000);    

要只读取文本文件,首先绝对不需要逐行解析文件。读取部分的正确工具是InputStreamReader,它将提供从文件编码到字符的转换。为了将实际的文件读取速度提高到合理的性能,在实际的FileInputStream和InputStreamReader之间放置一个BufferedInputStream

因此,要设置用于读取的文件,原则上可以嵌套三个源,如下所示:

InputStream is = new FileInputStream(...);
InputStream bi = new BufferedInputStream(is);
InputStreamReader reader = new InputStreamReader(bi, (CharSet));
实际读数是一个简单的循环,没有任何奇特的逻辑:

StringBuilder buffer = new StringBuilder();
// possible optimization would be: new StringBuilder((int) file.length());
int c = reader.read();
while (c >= 0) {
    buffer.append((char) c);
    c = reader.read();
}
(省略了错误处理和资源管理,实际上这需要try/catch来处理可能的异常)

由于文本文件已经包含换行符(自然),因此没有理由将其拆分为行,然后再将行重新组合在一起

最后,只需对缓冲区执行一个简单的toString(),您的字符串如下:

 String contents = buffer.toString();

此方法每次读取时不会创建任何中间对象(StringBuilder将其容量调整到一边)。它的复杂性基本上是O(N),这意味着所需的时间只会随着文件大小线性增加。

您仍然在创建新字符串,请执行:result.append(stringAdd.append(“\N”);我想你可以通过加快文件字符串的查找速度来减少时间,对吗?>你是从文件中读取的吗?您是否正在使用
缓冲读取器
?它的缓冲区大小是否足够大?您只是在附加到文件还是在修改它?啊哈,我将尝试这个结果。append(stringAdd).append('\n');再次测试。谢谢,关于新的StringBuilder(30_000),这是StringBuilder的固定大小,还是只是为了演示?我可以很容易地估计出字符串的大小+/-10%@Demosten这只是内部缓冲区大小的一个提示,如果您在其中投入更多,它仍然会增长。Houray!速度提高了一倍!对于440000行,程序现在完成9秒,之前超过30秒!谢谢。这个基数是从2个日志文件输入的。由于有很多更改和搜索,结果文件行与输入文件相比都混淆了。我不能从文件中读取jsut,进行更改并附加到StringBuffer。这就是为什么我使用字符串[]和整数[]来解析输入文件。但是对于新的StringBuilder((int)file.length())的提示非常好。它将使用它并测试它。