Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficient conversion of ArrayList<String[]> to multi-line String in JAVA

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";
}

My code is above. It works fine and produces exactly the result I want, just slowly. It takes about 10ms per item of ArrayList writtenClasses which is okay until I give it bigger jobs. I suspect that there is something there to do with ArrayLists that is taking so long, but timing and printing to console job stats after each run revealed little.

This above code is an adaptation of earlier code in hopes to improve efficiency. It does so by about 4%. The below code is the old method I used which takes just a little longer than the above.

for(String[] classLines: writtenClasses)
{
    for(String classLine: classLines)
    {
        result += classLine + "\n";
    }
    writtenClasses.set(writtenClasses.indexOf(classLines), null);
}

I do writtenClasses.set(writtenClasses.indexOf(classLines), null); merely for the purposes of memory efficiency, and my stats show that it uses memory more efficiently with an undetectable amount of CPU effort.

This is my second question here on StackOverflow and i've done my best to follow the rules, but if i'm asking this badly or being inadvertently inconsiderate in some way, please, highlight that to me and i'll address that. :)

like image 469
Scruffy Avatar asked Sep 09 '14 05:09

Scruffy


Video Answer


1 Answers

There is absolutely no use creating the intermediate processedClasses list. Also, StringBuilder will speed up significantly the process:

// 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();

We build the content in a StringBuilder which implements the CharSequence interface. Many classes accept CharSequences and not just Strings. A good example is a FileWriter. In these cases you don't even need to convert the StringBuilder to a String because the StringBuilder can be passed just as easily as its String result which may be another performance advantage if the content is really big.

like image 53
icza Avatar answered Oct 30 '22 23:10

icza