ArrayList<String[]> writtenClasses = new ArrayList<String[]>();
// usually there is functional code here that populates
// ArrayList<String[]> writtenClasses with variably 3000
// String[] objects always of exactly 8 lines each
ArrayList<String> processedClasses = new ArrayList<String>();
for(String[] classLines: writtenClasses)
{
for(String classLine: classLines)
{
processedClasses.add(classLine);
}
}
String result = "";
for(String fileLine: processedClasses)
{
result += fileLine + "\n";
}
我的代码在上面。它工作正常,产生我想要的结果,只是缓慢。每个项目的ArrayList书写类需要大约10毫秒,这是好的,直到我给它更大的工作。我怀疑与ArrayLists有关的事情已经花了这么长时间,但是在每次运行后,计时器和打印到控制台工作统计数据都显得很少。
上面的代码是对早期代码的改编,希望能提高效率。它的成功率约为4%。下面的代码是我使用的旧方法,它只需要比上面更长的时间。
for(String[] classLines: writtenClasses)
{
for(String classLine: classLines)
{
result += classLine + "\n";
}
writtenClasses.set(writtenClasses.indexOf(classLines), null);
}
我只是为了提高内存效率而writtenClasses.set(writtenClasses.indexOf(classLines), null);
,而我的统计数据显示,它在不可检测的CPU工作量下更有效地使用内存。
这是我在StackOverflow上的第二个问题,我已尽力遵守规则,但如果我对此表示严重或在某种程度上无意中不注意,请向我强调我会解决这个问题。 :)
答案 0 :(得分:3)
创建中间processedClasses
列表绝对没用。此外,StringBuilder
将显着加快流程:
// Consider a large initial size to even avoid reallocation, here I used 64 KB
StringBuilder sb = new StringBuilder(65536);
for (String[] classLines : writtenClasses)
for (String lines : classLines)
sb.append(lines).append('\n');
// Note: you might not even need to convert it to String, read reasoning below
String result = sb.toString();
我们在StringBuilder中构建内容,该StringBuilder实现CharSequence
接口。许多课程都接受CharSequence
而不只是String
。一个很好的例子是FileWriter
。在这些情况下,您甚至无需将StringBuilder
转换为String
,因为StringBuilder
可以像String
结果一样轻松传递,这可能是另一种表现如果内容非常大,则有优势。
答案 1 :(得分:2)
其他答案已经指出了这个问题。使用Java 8,两个嵌套循环和StringBuilder的替代方法是使用流和连接收集器*:
String result = writtenClasses.stream()
.flatMap(array -> Arrays.stream(array))
.collect(joining("\n"));
*需要import static java.util.Collectors.joining;
答案 2 :(得分:1)
不是一个正确的答案,但在评论中读得太尴尬了:
String result = "";
for(String fileLine: processedClasses)
{
result += fileLine + "\n";
}
这就是创建了一百万个String实例。我想在这里使用StringBuilder
会对性能产生积极影响。
答案 3 :(得分:1)
这里的主要痛点可能不是ArrayList
,而是+
运算符与String
的使用。由于String
在java中是不可变的,因此每次调用都会强制创建一个新对象并复制所有数据,正如您所说,这些数据可能会很长。
更快的方法是使用StringBuilder
,它不会(必然)强制复制每个操作的数据:
StringBuilder result = new StringBuilder();
for(String[] classLines: writtenClasses)
{
for(String classLine: classLines)
{
result.append(classLine).append('\n');
}
}
答案 4 :(得分:0)
基于此question
ewall:
At what point do you switch to StringBuilder? When it effects memory or performance. Or when it might. If you're really only doing this for a couple strings once, no worries. But if you're going to be doing it over and over again, you should see a measurable difference when using StringBuilder.
StringBuilder myString = new StringBuilder();
for(String classLine: classLines)
{
myString.append(classLine).append("\n");
}
StringBuilder
会以某种方式改善您的表现。