В основному, використання циклу для повторення над ArrayList
єдиним варіантом:
НЕ використовуйте цей код, продовжуйте читати донизу цю відповідь, щоб побачити, чому це не бажано, і який код слід використовувати замість цього:
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
String listString = "";
for (String s : list)
{
listString += s + "\t";
}
System.out.println(listString);
Насправді, конкатенація рядків буде просто чудовою, оскільки javac
компілятор оптимізує конкатенацію рядків як серію append
операцій у StringBuilder
будь-якому разі. Ось частина розбирання байт-коду з for
циклу з вищевказаної програми:
61: new #13; //class java/lang/StringBuilder
64: dup
65: invokespecial #14; //Method java/lang/StringBuilder."<init>":()V
68: aload_2
69: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
72: aload 4
74: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
77: ldc #16; //String \t
79: invokevirtual #15; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
82: invokevirtual #17; //Method java/lang/StringBuilder.toString:()Ljava/lang/String;
Як видно, компілятор оптимізує цю петлю за допомогою a StringBuilder
, тому продуктивність не повинна викликати особливих проблем.
(Гаразд, з другого погляду, StringBuilder
інстанціюється при кожній ітерації циклу, тому це може бути не найефективнішим байт-кодом. Моментальне використання та використання явного StringBuilder
, можливо, дасть кращі показники.)
Насправді, я думаю, що мати будь-який вихід (будь то на диск чи на екран) буде щонайменше на порядок повільніше, ніж турбуватися про продуктивність струнних конкатенацій.
Редагування: Як зазначено в коментарях, вищеописана оптимізація компілятора справді створює новий примірник для StringBuilder
кожної ітерації. (Що я вже відзначав раніше.)
Найбільш оптимізованою технікою для використання буде відповідь Пола Томбліна , оскільки вона створює лише один StringBuilder
об'єкт поза for
циклом.
Переписання вищевказаного коду на:
ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");
StringBuilder sb = new StringBuilder();
for (String s : list)
{
sb.append(s);
sb.append("\t");
}
System.out.println(sb.toString());
Буде інстанціювати лише StringBuilder
один раз зовні цикл, і лише зробить два виклики append
методу всередині циклу, про що свідчить цей байт-код (який показує інстанціювання StringBuilder
і цикл):
// Instantiation of the StringBuilder outside loop:
33: new #8; //class java/lang/StringBuilder
36: dup
37: invokespecial #9; //Method java/lang/StringBuilder."<init>":()V
40: astore_2
// [snip a few lines for initializing the loop]
// Loading the StringBuilder inside the loop, then append:
66: aload_2
67: aload 4
69: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
72: pop
73: aload_2
74: ldc #15; //String \t
76: invokevirtual #14; //Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;
79: pop
Таким чином, оптимізація руки повинна бути ефективнішою, оскільки внутрішня for
петля коротшає, і немає необхідності вводити копії StringBuilder
на кожну ітерацію.