По сути, использование цикла для итерации 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;
Как видно, компилятор оптимизирует этот цикл с помощью 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
цикла короче и нет необходимости создавать экземпляр a StringBuilder
на каждой итерации.