Mam coś ArrayList
, co chcę wyprowadzić całkowicie jako ciąg. Zasadniczo chcę wyprowadzać go w kolejności, używając toString
każdego elementu oddzielonego tabulatorami. Czy jest jakiś szybki sposób na to? Możesz przejść przez niego (lub usunąć każdy element) i połączyć go w ciąg znaków, ale myślę, że będzie to bardzo powolne.
353
Odpowiedzi:
Zasadniczo użycie pętli do iteracji
ArrayList
jest 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:
W rzeczywistości konkatenacja łańcuchów będzie w porządku, ponieważ
javac
kompilator zoptymalizuje konkatenację łańcuchów jako serięappend
operacjiStringBuilder
. Oto część demontażu kodu bajtowego zfor
pętli z powyższego programu: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
StringBuilder
instancja jest tworzona przy każdej iteracji pętli, więc może nie być najbardziej wydajnym kodem bajtowym. Tworzenie instancji i używanie jawnegoStringBuilder
prawdopodobnie 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
StringBuilder
każdej iteracji. (Które zauważyłem wcześniej.)Najbardziej zoptymalizowaną techniką do zastosowania będzie odpowiedź Paula Tomblina , ponieważ tworzy ona tylko pojedynczy
StringBuilder
obiekt pozafor
pętlą.Przepisanie powyższego kodu do:
Utworzy tylko
StringBuilder
jedną instancję poza pętlą i wykona tylko dwa wywołaniaappend
metody wewnątrz pętli, jak pokazano w tym kodzie bajtowym (który pokazuje instancjęStringBuilder
i pętlę):Rzeczywiście, optymalizacja ręki powinna być lepsza, ponieważ wnętrze
for
pętli jest krótsze i nie ma potrzeby tworzenia wystąpieniaStringBuilder
przy każdej iteracji.źródło
Java
lub Geewax forAndroid
W Javie 8 lub nowszej:
W przypadku, gdy
list
nie jest typu String, można użyć łączącego kolektora:źródło
Jeśli robisz to na Androidzie, istnieje przyjemne narzędzie do tego o nazwie TextUtils, które ma
.join(String delimiter, Iterable)
metodę.Oczywiście niewiele poza Androidem, ale pomyślałem, że dodam go do tego wątku ...
źródło
TextUtils.join
trwa anObject[]
, zakładam, że wywołujetoString()
każdy token. CzyPatientDetails
implementujetoString()
? Jeśli to nie rozwiąże problemu, możesz utknąć, robiąc coś zSeparator
klasą.org.apache.lang3.StringUtils
robi praktycznie to samo, więc twoja odpowiedź była dla mnie bardzo przydatna poza Androidem :)Pobierz Apache Commons Lang i skorzystaj z metody
Oczywiście możesz to zaimplementować samodzielnie, ale ich kod jest w pełni przetestowany i prawdopodobnie jest to najlepsza możliwa implementacja.
Jestem wielkim fanem biblioteki Apache Commons i uważam również, że jest to świetny dodatek do biblioteki Java Standard Library.
źródło
StringUtils.join(list.toArray(),"\t")
To dość stare pytanie, ale myślę, że równie dobrze mogę dodać bardziej nowoczesną odpowiedź - skorzystaj z
Joiner
klasy z Guawy :źródło
Zmiana listy na czytelny i znaczący ciąg znaków jest tak naprawdę częstym pytaniem, z którym każdy może się spotkać.
Przypadek 1 . Jeśli masz aplet StringUtils na swojej ścieżce klasy (jak z rogerdpack i Ravi Wallau):
Przypadek 2 . Jeśli chcesz korzystać tylko z JDK (7):
Po prostu nigdy nie buduj samodzielnie kół, nie używaj pętli do tego zadania w jednej linii.
źródło
Arrays.toString(myList.toArray())
- najłatwiejsze i najprostsze rozwiązanieArrays.toString(list.toArray())
jest łatwy do napisania, ale wysoce nieefektywny.Jeśli szukałeś szybkiego jednuliniowego oprogramowania, od wersji Java 5 możesz to zrobić:
Dodatkowo, jeśli Twoim celem jest jedynie wydrukowanie zawartości i nie martwisz się o „\ t”, możesz po prostu to zrobić:
który zwraca ciąg podobny do
Jeśli masz tablicę (nie ArrayList), możesz wykonać to samo:
źródło
m
gospodarstwach domowych wn
miastach wx
stanach, powiedziałbyś, że toO(mnx)
lubO(n^3)
, ale mogę to przeformułować, aby powiedzieć „szukaj tej osoby w tym kraju”, i natychmiast byś mi powiedziałO(n)
. Ponadto wszystkie algorytmy tutaj są generalnieO(n)
, nie ma pętli w pętli.Pętlę i wywoływanie toString. Nie ma magicznego sposobu, a jeśli tak, to co, według niego, działałoby pod przykryciem innym niż przechodzenie przez niego? Jedyną mikrooptymalizacją byłoby użycie StringBuilder zamiast String, a nawet to nie jest ogromna wygrana - łączenie łańcuchów zamienia się w StringBuilder pod przykryciem, ale przynajmniej jeśli napiszesz to w ten sposób, zobaczysz, co się dzieje.
źródło
Większość projektów Java ma często dostępny język apache-commons. Metody StringUtils.join () są bardzo ładne i mają kilka smaków, które zaspokoją prawie każdą potrzebę.
źródło
join(...)
metoda ma warianty zarówno dla tablic, jak i kolekcji.Android ma klasę TextUtil, z której można korzystać http://developer.android.com/reference/android/text/TextUtils.html
źródło
W tym prostym przypadku użycia możesz po prostu połączyć ciągi przecinkiem. Jeśli używasz Java 8:
w przeciwnym razie commons-lang ma metodę join ():
źródło
Eleganckim sposobem radzenia sobie z końcowymi znakami separacji jest użycie separatora klas
Metoda toString klasy Separator zwraca separator, z wyjątkiem pierwszego wywołania. Dlatego drukujemy listę bez końcowych (lub w tym przypadku) wiodących separatorów.
źródło
W Javie 8 jest to proste. Zobacz przykład listy liczb całkowitych:
Lub wersja wielowierszowa (łatwiejsza do odczytania):
Aktualizacja - krótsza wersja
źródło
filter
. W końcu znacznie łatwiej jest mi odczytać kod.String
również. Jeśli jest to lista zInteger
którymi masz problemTo jest
O(n)
algorytm w obu kierunkach (chyba że wykonałeś jakieś wielowątkowe rozwiązanie, w którym podzieliłeś listę na wiele list podrzędnych, ale nie sądzę, że o to prosisz).Po prostu użyj
StringBuilder
poniższego:StringBuilder
Będzie dużo szybciej niż ciąg konkatenacji, ponieważ nie będzie ponowne utworzenie wystąpieniaString
obiektu na każdej konkatenacji.źródło
Jeśli zdarzyło Ci się być na Androidzie i jeszcze nie używasz Jacka (np. Ponieważ wciąż brakuje wsparcia dla Instant Run) i jeśli chcesz mieć większą kontrolę nad formatowaniem wynikowego łańcucha (np. Chciałbyś użyć znaku nowej linii jako dzielnik elementów) i zdarzyło się użyć / chcesz użyć biblioteki StreamSupport (do korzystania ze strumieni w Javie 7 lub wcześniejszych wersjach kompilatora), możesz użyć czegoś takiego (umieściłem tę metodę w mojej klasie ListUtils):
I oczywiście upewnij się, że zaimplementowałeś toString () w klasie obiektów listy.
źródło
reduce
jest wyjątkowo nieefektywne w przypadku konkatenacji ciągów. Powinieneś to zrobić w sposóbreturn StreamSupport.stream(list).map(Object::toString).collect(joining("\n"))
używany w Javie 8StringJoiner
. Nie ma powodu, dla którego nie można tego zrobić również z obsługą streamingu .Optional#get
), gdyby otrzymał pustą listę.Jeśli nie chcesz ostatniego \ t po ostatnim elemencie, musisz użyć indeksu do sprawdzenia, ale pamiętaj, że to „działa” (tj. O (n)), gdy listy implementują RandomAccess.
źródło
Poniższy kod może ci pomóc,
Wynik:
źródło
Może nie być najlepszy, ale elegancki sposób.
Arrays.deepToString (Arrays.asList („Test”, „Test2”)
Wynik
[Test, Test2]
źródło
Czy byłoby coś dobrego:
źródło
Jeśli korzystasz z kolekcji Eclipse , możesz użyć tej
makeString()
metody.Jeśli możesz przekonwertować swój
ArrayList
naFastList
, możesz pozbyć się adaptera.Uwaga: jestem osobą odpowiedzialną za kolekcje Eclipse.
źródło
Przechodzisz do
new StringJoiner
sekwencji char, której chcesz użyć jako separatora. Jeśli chcesz zrobić plik CSV:new StringJoiner(", ");
źródło
W jednej linii: od [12,0,1,78,12] do 12 0 1 78 12
źródło
Do oddzielania za pomocą zakładek zamiast println możesz użyć print
źródło
Widzę kilka przykładów, które zależą od dodatkowych zasobów, ale wydaje się, że byłoby to najprostsze rozwiązanie: (tego właśnie użyłem w swoim własnym projekcie), który w zasadzie jest po prostu konwertowany z ArrayList na Array, a następnie na Listę .
źródło
To już dość stara rozmowa, a wspólne apache używają teraz StringBuilder wewnętrznie: http://commons.apache.org/lang/api/src-html/org/apache/commons/lang/StringUtils.html#line. 3045
Jak wiemy, poprawi to wydajność, ale jeśli wydajność ma kluczowe znaczenie, zastosowana metoda może być nieco nieefektywna. Chociaż interfejs jest elastyczny i pozwoli na spójne zachowanie różnych typów kolekcji, jest on nieco nieefektywny w przypadku list, co jest rodzajem kolekcji w pierwotnym pytaniu.
Opieram to na tym, że ponosimy pewne koszty ogólne, których unikalibyśmy, po prostu iterując elementy w tradycyjnej pętli for. Zamiast tego za kulisami dzieją się pewne dodatkowe rzeczy, które sprawdzają, czy są równoległe modyfikacje, wywołania metod itp. Ulepszona pętla for spowoduje z drugiej strony ten sam narzut, ponieważ iterator jest używany na obiekcie Iterable (List).
źródło
Możesz do tego użyć Regex. To jest tak zwięzłe, jak to możliwe
źródło
A co z tą funkcją:
działa dla każdego rodzaju kolekcji ...
źródło