Zasadniczo użycie pętli do iteracji ArrayListjest jedyną opcją:
NIE używaj tego kodu, kontynuuj czytanie na dole tej odpowiedzi, aby zobaczyć, dlaczego nie jest pożądane, i który kod należy zastosować zamiast tego:
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);
W rzeczywistości konkatenacja łańcuchów będzie w porządku, ponieważ javackompilator zoptymalizuje konkatenację łańcuchów jako serię appendoperacji StringBuilder. Oto część demontażu kodu bajtowego z forpętli z powyższego programu:
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;
Jak widać, kompilator optymalizuje tę pętlę za pomocą a StringBuilder, więc wydajność nie powinna być dużym problemem.
(OK, na drugi rzut oka StringBuilderinstancja jest tworzona przy każdej iteracji pętli, więc może nie być najbardziej wydajnym kodem bajtowym. Tworzenie instancji i używanie jawnego StringBuilderprawdopodobnie poprawiłoby wydajność.)
W rzeczywistości myślę, że posiadanie jakiegokolwiek wyjścia (czy to na dysk, czy na ekran) będzie co najmniej o rząd wielkości wolniejsze niż martwienie się o wydajność konkatenacji łańcuchów.
Edycja: Jak wskazano w komentarzach, powyższa optymalizacja kompilatora rzeczywiście tworzy nowe wystąpienie StringBuilderkażdej iteracji. (Które zauważyłem wcześniej.)
Najbardziej zoptymalizowaną techniką do zastosowania będzie odpowiedź Paula Tomblina , ponieważ tworzy ona tylko pojedynczy StringBuilderobiekt poza forpętlą.
Przepisanie powyższego kodu do:
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());
Utworzy tylko StringBuilderjedną instancję poza pętlą i wykona tylko dwa wywołania appendmetody wewnątrz pętli, jak pokazano w tym kodzie bajtowym (który pokazuje instancję StringBuilderi pętlę):
// 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
Rzeczywiście, optymalizacja ręki powinna być lepsza, ponieważ wnętrze forpętli jest krótsze i nie ma potrzeby tworzenia wystąpienia StringBuilderprzy każdej iteracji.