Najlepszy sposób na konwersję ArrayList na ciąg znaków

Mam ArrayList, który chcę wypisać jako ciąg znaków. Zasadniczo chcę wypisać go w kolejności za pomocą toString każdego elementu oddzielonego tabulatorami. Jest na to jakiś szybki sposób? Możesz przebić go w pętlę (lub usunąć każdy element) i połączyć go z ciągiem znaków, ale myślę, że będzie to bardzo powolne.

Author: Hamid Pourjam, 2009-03-01

28 answers

Zasadniczo, użycie pętli do iteracji nad ArrayList jest jedyną opcją:

Nie używaj tego kodu, Czytaj dalej na dole tej odpowiedzi, aby zobaczyć, dlaczego nie jest to pożądane i który kod powinien być użyty zamiast tego: {21]}

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ż kompilator javac zoptymalizuje konkatenację łańcuchów jako serię operacji append na StringBuilder. Oto część demontażu kodu bajtowego z for pętla 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ą StringBuilder, więc wydajność nie powinna być wielkim problemem.

(OK, na drugi rzut oka StringBuilder jest tworzona instancja przy każdej iteracji pętli, więc może nie być to najbardziej efektywny bajt. Utworzenie instancji i użycie jawnego StringBuilder prawdopodobnie przyniosłoby lepszą wydajność.)

W zasadzie myślę, że każdy rodzaj wyjścia (czy to na dysk czy na ekran) będzie co najmniej o rząd wielkości wolniejszy od konieczności martwienia się o wydajność konkatenacji strun.

Edit: Jak wspomniano w komentarzach, powyższa optymalizacja kompilatora rzeczywiście tworzy nową instancję StringBuilder na każdej iteracji. (Co już wcześniej odnotowałem.)

Najbardziej zoptymalizowaną techniką będzie odpowiedź Paula Tomblina , ponieważ tworzy ona tylko jeden obiekt StringBuilder poza pętlą for.

Przepisanie do powyższego kod 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 instancję StringBuilder tylko raz poza pętlą i wywoła tylko dwa wywołania metody append wewnątrz pętli, co udowodniono w tym bajtowym kodzie (który pokazuje instancję StringBuilder i pętli):

   // 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

Tak więc optymalizacja ręki powinna być bardziej efektywna, ponieważ wnętrze pętli for jest krótsze i nie ma potrzeby tworzenia instancji StringBuilder przy każdej iteracji.

 294
Author: coobird,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:59

W Javie 8 lub nowszej:

String listString = String.join(", ", list);

W przypadku, gdy list nie jest typu String, można użyć kolektora łączącego:

String listString = list.stream().map(Object::toString)
                        .collect(Collectors.joining(", "));
 625
Author: Vitalii Fedorenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-23 00:04:10

Jeśli przypadkiem robisz to na Androidzie, istnieje ładne narzędzie do tego o nazwie TextUtils , które ma metodę .join(String delimiter, Iterable).

List<String> list = new ArrayList<String>();
list.add("Item 1");
list.add("Item 2");
String joined = TextUtils.join(", ", list);

Oczywiście nie ma większego zastosowania poza Androidem, ale pomyślałem, że dodam go do tego wątku...

 347
Author: JJ Geewax,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-15 17:29:53

Pobierz Jakarta Commons Lang i użyj metody

 StringUtils.join(list)

Można oczywiście zaimplementować go samodzielnie, ale ich kod jest w pełni przetestowany i jest prawdopodobnie najlepszą możliwą implementacją.

Jestem wielkim fanem Jakarta Commons library i uważam, że jest to świetny dodatek do standardowej biblioteki Javy.

 199
Author: Ravi Wallau,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-19 18:29:26

To dość stare pytanie, ale pomyślałem, że równie dobrze mogę dodać bardziej nowoczesną odpowiedź-użyj Joiner klasa z :

String joined = Joiner.on("\t").join(list);
 134
Author: Jon Skeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-01 15:37:28

Zmiana Listy na czytelny i znaczący Ciąg jest naprawdę częstym pytaniem, z którym każdy może się spotkać.

Przypadek 1 . Jeśli masz Stringutile apache ' a w swojej ścieżce klasowej (od rogerdpack i Ravi Wallau):

import org.apache.commons.lang3.StringUtils;
String str = StringUtils.join(myList);

Przypadek 2 . Jeśli chcesz używać tylko sposobów z JDK (7):

import java.util.Arrays;
String str = Arrays.toString(myList.toArray()); 

Po prostu nigdy nie buduj kół samodzielnie, nie używaj pętli do tego jednoliniowego zadania.

 70
Author: Sheng.W,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-24 15:09:06

Jeśli szukałeś szybkiego jednowiersza, od Javy 5 możesz to zrobić:

myList.toString().replaceAll("\\[|\\]", "").replaceAll(", ","\t")

Dodatkowo, jeśli twoim celem jest tylko wydrukowanie treści i mniej martwisz się o "\ t", możesz po prostu to zrobić:

myList.toString()

Który zwraca łańcuch jak

[str1, str2, str3]

Jeśli masz tablicę (nie ArrayList), możesz wykonać to samo w następujący sposób:

 Arrays.toString(myList).replaceAll("\\[|\\]", "").replaceAll(", ","\t")
 55
Author: Ken Shih,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-05 20:52:09

Przeprowadź pętlę i wywołaj toString. Nie ma magicznego sposobu, A gdyby tak było, to jak myślisz, co robiłoby pod kołdrą, poza zapętleniem? O jedyną mikro-optymalizacją byłoby użycie Stringbuildera zamiast String, a nawet to nie jest wielka wygrana-konkatenacja ciągów zamienia się w StringBuilder pod okładkami, ale przynajmniej jeśli piszesz to w ten sposób, możesz zobaczyć, co się dzieje.

StringBuilder out = new StringBuilder();
for (Object o : list)
{
  out.append(o.toString());
  out.append("\t");
}
return out.toString();
 37
Author: Paul Tomblin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-04-15 14:12:22

Większość projektów Java często posiada Apache-commons lang. StringUtils.metoda join () jest bardzo przyjemna i ma kilka smaków, aby zaspokoić prawie każdą potrzebę.

public static java.lang.String join(java.util.Collection collection,
                                    char separator)


public static String join(Iterator iterator, String separator) {
    // handle null, zero and one elements before building a buffer 
    Object first = iterator.next();
    if (!iterator.hasNext()) {
        return ObjectUtils.toString(first);
    }
    // two or more elements 
    StringBuffer buf = 
        new StringBuffer(256); // Java default is 16, probably too small 
    if (first != null) {
        buf.append(first);
    }
    while (iterator.hasNext()) {
        if (separator != null) {
            buf.append(separator);
        }
        Object obj = iterator.next();
        if (obj != null) {
            buf.append(obj);
        }
    }
    return buf.toString();
}

Parametry:

Zbiór - zbiór wartości do połączenia, może być null

Separator - znak separatora do użycia

Returns: połączony Łańcuch, null if null iterator input

Od: 2.3

 35
Author: Brian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-01 04:49:46

Android ma klasę TextUtil, której możesz użyć http://developer.android.com/reference/android/text/TextUtils.html

String implode = TextUtils.join("\t", list);
 14
Author: kehers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-12 05:11:48

Eleganckim sposobem radzenia sobie z końcowymi znakami separacyjnymi jest użycie separatora klasy

StringBuilder buf = new StringBuilder();
Separator sep = new Separator("\t");
for (String each: list) buf.append(sep).append(each);
String s = buf.toString();

Metoda ToString klasy Separator zwraca separater, z wyjątkiem dla pierwszego wywołania. W ten sposób drukujemy listę bez końcowych (lub w tym przypadku) wiodących separatorów.

 12
Author: akuhn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-23 06:26:49

W tym prostym przypadku można po prostu połączyć ciągi znaków przecinkiem. Jeśli używasz Javy 8:

String csv = String.join("\t", yourArray);

W przeciwnym razie commons-lang ma metodę join ():

String csv = org.apache.commons.lang3.StringUtils.join(yourArray, "\t");
 7
Author: Khader M A,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-29 02:49:36

To algorytm O(n) tak czy inaczej (chyba, że zrobiłeś jakieś wielowątkowe rozwiązanie, w którym podzieliłeś listę na wiele podlist, ale nie sądzę, że o to prosisz).

Wystarczy użyć StringBuilder Jak poniżej:

StringBuilder sb = new StringBuilder();

for (Object obj : list) {
  sb.append(obj.toString());
  sb.append("\t");
}

String finalString = sb.toString();

StringBuilder będzie o wiele szybsza niż konkatenacja ciągu znaków, ponieważ nie będziesz ponownie tworzyć instancji String obiektu przy każdej konkatenacji.

 6
Author: Mike C.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-11-17 14:02:28

ArrayList class (Java Docs ) extends AbstractList class, która rozszerza AbstractCollection class, która zawiera metodętoString() (Java Docs ). Więc po prostu napisz

listName.toString();

Programiści Javy już wymyślili najbardziej efektywny sposób i dali ci to w ładnie zapakowanej i udokumentowanej metodzie. Po prostu zadzwoń do tej metody.

 6
Author: golddove,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-06 14:56:05

W przypadku, gdy zdarzy ci się, że jesteś na Androidzie i nie używasz jeszcze Jack (np. ponieważ wciąż brakuje wsparcia dla Instant Run), i jeśli chcesz mieć większą kontrolę nad formatowaniem wynikowego ciągu znaków (np. chcesz użyć znaku nowej linii jako dzielnika elementów), a zdarzyło ci się użyć / want to use biblioteki StreamSupport (do korzystania ze strumieni w Java 7 lub wcześniejszych wersjach kompilatora), możesz użyć czegoś takiego (umieściłem tę metodę w mojej liście Klasa): {]}

public static <T> String asString(List<T> list) {
    return StreamSupport.stream(list)
            .map(Object::toString)
            .collect(Collectors.joining("\n"));
}

I oczywiście upewnij się, że zaimplementowałeś ToString () w klasie obiektów listy.

 5
Author: Javad Sadeqzadeh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-09-26 18:44:37

Może nie jest to najlepszy sposób, ale elegancki sposób.

Tablice.deepToString (Węg.asList ("Test","Test2")

import java.util.Arrays;

    public class Test {
        public static void main(String[] args) {
            System.out.println(Arrays.deepToString(Arrays.asList("Test", "Test2").toArray()));
        }
    }

Wyjście

[Test, Test2]

 3
Author: Mohan Narayanaswamy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-03 02:49:13

Jeśli używasz kolekcji Eclipse , możesz użyć metody makeString().

ArrayList<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

Assert.assertEquals(
    "one\ttwo\tthree",
    ArrayListAdapter.adapt(list).makeString("\t"));

Jeśli możesz przekonwertować ArrayList na FastList, możesz pozbyć się adaptera.

Assert.assertEquals(
    "one\ttwo\tthree",
    FastList.newListWith("one", "two", "three").makeString("\t"));

Uwaga: jestem committerem Dla Kolekcji Eclipse.

 3
Author: Craig P. Motlin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-15 18:28:15
List<String> stringList = getMyListOfStrings();
StringJoiner sj = new StringJoiner(" ");
stringList.stream().forEach(e -> sj.add(e));
String spaceSeparated = sj.toString()

PRZEKAZUJESZ do new StringJoiner sekwencję znaków, którą chcesz użyć jako separatora. Jeśli chcesz zrobić plik CSV: new StringJoiner(", ");

 3
Author: fmsf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-08 11:16:45

Poniższy kod może Ci pomóc,

List list = new ArrayList();
list.add("1");
list.add("2");
list.add("3");
String str = list.toString();
System.out.println("Step-1 : " + str);
str = str.replaceAll("[\\[\\]]", "");
System.out.println("Step-2 : " + str);

Wyjście:

Step-1 : [1, 2, 3]
Step-2 : 1, 2, 3
 2
Author: Srinivasan.S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-20 10:35:25

W Javie 8 to proste. Zobacz przykład dla listy liczb całkowitych:

String result = Arrays.asList(1,2,3).stream().map(Object::toString).reduce((t, u) -> t + "\t" + u).orElse("");

Lub wersja wielowierszowa (prostsza do odczytania):

String result = Arrays.asList(1,2,3).stream()
    .map(Object::toString)
    .reduce((t, u) -> t + "\t" + u)
    .orElse("");
 2
Author: amra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-05-06 10:04:36

Czy to byłoby dobre:

List<String> streamValues = new ArrayList<>();
Arrays.deepToString(streamValues.toArray()));   
 2
Author: Beezer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-12-10 16:55:14

Jeśli nie chcesz ostatniego \t po ostatnim elemencie, musisz użyć indeksu, aby sprawdzić, ale pamiętaj, że to tylko "działa" (tzn. jest O (n)), gdy lists implementuje RandomAccess.

List<String> list = new ArrayList<String>();
list.add("one");
list.add("two");
list.add("three");

StringBuilder sb = new StringBuilder(list.size() * apprAvg); // every apprAvg > 1 is better than none
for (int i = 0; i < list.size(); i++) {
    sb.append(list.get(i));
    if (i < list.size() - 1) {
        sb.append("\t");
    }
}
System.out.println(sb.toString());
 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-01 10:07:35

Do oddzielania za pomocą tabulatorów zamiast println możesz użyć print

  ArrayList<String> mylist = new ArrayList<String>();
    mylist.add("C Programming");
    mylist.add("Java");
    mylist.add("C++");
    mylist.add("Perl");
    mylist.add("Python");


    for (String each : mylist)
    {

        System.out.print(each);
        System.out.print("\t");
    }
 1
Author: chopss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-31 05:36:40

Widzę sporo przykładów, które zależą od dodatkowych zasobów, ale wydaje się, że byłoby to najprostsze rozwiązanie: (czego użyłem w moim własnym projekcie), który jest w zasadzie tylko konwersją z ArrayList do tablicy, a następnie do listy.

    List<Account> accounts = new ArrayList<>();

   public String accountList() 
   {
      Account[] listingArray = accounts.toArray(new Account[accounts.size()]);
      String listingString = Arrays.toString(listingArray);
      return listingString;
   }
 1
Author: Elliander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-24 20:27:49

To już dość stara rozmowa i Apache commons używa teraz wewnętrznie Stringbuildera: http://commons.apache.org/lang/api/src-html/org/apache/commons/lang/StringUtils.html#line.3045

To, jak wiemy, poprawi wydajność, ale jeśli wydajność jest krytyczna, zastosowana metoda może być nieco nieefektywna. Podczas gdy interfejs jest elastyczny i pozwoli na spójne zachowanie w różnych typach kolekcji, jest on nieco nieefektywny w przypadku list, jaki jest rodzaj zbioru w pytaniu pierwotnym.

Bazuję na tym, że ponosimy pewne koszty, których unikniemy, po prostu iterując przez elementy w tradycyjnej pętli for. Zamiast tego za kulisami dzieje się kilka dodatkowych rzeczy, które sprawdzają współbieżne modyfikacje, wywołania metod itp. Z drugiej strony pętla enhanced for spowoduje ten sam narzut, ponieważ iterator jest używany na obiekcie Iterable (lista).

 0
Author: Alex VI,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-07-13 00:21:32

Możesz użyć do tego wyrażenia regularnego. To jest tak zwięzłe, jak się wydaje

System.out.println(yourArrayList.toString().replaceAll("\\[|\\]|[,][ ]","\t"));
 0
Author: Vikrant Goel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-08 07:40:40

A może ta funkcja:

public static String toString(final Collection<?> collection) {
    final StringBuilder sb = new StringBuilder("{");
    boolean isFirst = true;
    for (final Object object : collection) {
        if (!isFirst)
            sb.append(',');
        else
            isFirst = false;
        sb.append(object);
    }
    sb.append('}');
    return sb.toString();
}

Działa dla każdego typu kolekcji...

 -1
Author: android developer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-01-30 08:59:22

W jednej linii : Od [12,0,1,78,12] do 12 0 1 78 12

String srt= list.toString().replaceAll("\\[|\\]|,","");
 -2
Author: Pratyush Pranjal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-13 13:24:34