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.
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.
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(", "));
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...
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.
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);
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.
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")
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();
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
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);
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.
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");
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.
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.
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.
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]
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.
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(", ");
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
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("");
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()));
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());
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");
}
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;
}
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).
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"));
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...
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("\\[|\\]|,","");
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