Muszę połączyć dwie String
tablice w Javie.
void f(String[] first, String[] second) {
String[] both = ???
}
Jak najłatwiej to zrobić?
java
arrays
concatenation
add
Antti Kissaniemi
źródło
źródło
array1 + array2
konkatenacji.Odpowiedzi:
Znalazłem jedno-liniowe rozwiązanie ze starej dobrej biblioteki Apache Commons Lang.
ArrayUtils.addAll(T[], T...)
Kod:
źródło
Oto prosta metoda, która połączy dwie tablice i zwróci wynik:
Pamiętaj, że nie będzie działać z pierwotnymi typami danych, tylko z typami obiektów.
Poniższa nieco bardziej skomplikowana wersja działa zarówno z tablicami obiektowymi, jak i pierwotnymi. Robi to za pomocą
T
zamiastT[]
jako typu argumentu.Umożliwia także łączenie tablic dwóch różnych typów poprzez wybranie najbardziej ogólnego typu jako typu komponentu wyniku.
Oto przykład:
źródło
Array.newInstance(a.getClass().getComponentType(), aLen + bLen);
. Zaskakująco nigdy wcześniej tego nie widziałem. @beaudet Myślę, że adnotacja jest tutaj dobra, biorąc pod uwagę, dlaczego jest tłumiona.Możliwe jest napisanie w pełni ogólnej wersji, którą można nawet rozszerzyć, aby połączyć dowolną liczbę tablic. Te wersje wymagają Java 6, tak jak używają
Arrays.copyOf()
Obie wersje unikają tworzenia jakichkolwiek
List
obiektów pośrednich i używają,System.arraycopy()
aby zapewnić, że kopiowanie dużych tablic jest tak szybkie jak to możliwe.W przypadku dwóch tablic wygląda to tak:
A dla dowolnej liczby tablic (> = 1) wygląda to tak:
źródło
T
z nichbyte
(i stracisz<T>
).ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
concat(ai, ad)
gdzieai
jestInteger[]
iad
jestDouble[]
. (W tym przypadku parametr Typ<T>
zostanie rozwiązany<? extends Number>
przez kompilator). Tablicy utworzonej przezArrays.copyOf
będzie miał typu części pierwszej tablicy, to znaczyInteger
w tym przykładzie. Gdy funkcja ma zamiar skopiować drugą tablicę,ArrayStoreException
zostanie wyrzucony znak an . Rozwiązaniem jest mieć dodatkowyClass<T> type
parametr.Korzystanie
Stream
z Java 8:Lub w ten sposób, używając
flatMap
:Aby to zrobić dla typu ogólnego, musisz użyć odbicia:
źródło
.boxed()
takie, aby były typu,Stream
a nie np.IntStream
Które nie mogą być przekazane jako parametr doStream.concat
.a
ib
sąint[]
, użyjint[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
System.arrayCopy
. Ale też niezbyt powolny. Prawdopodobnie masz zrobić to na bardzo wiele razy z ogromnych tablic w naprawdę wrażliwych wydajności kontekstów dla różnicy czasu wykonanie znaczenia.Lub z ukochaną Guawą :
Istnieją również wersje prymitywnych tablic:
Booleans.concat(first, second)
Bytes.concat(first, second)
Chars.concat(first, second)
Doubles.concat(first, second)
Shorts.concat(first, second)
Ints.concat(first, second)
Longs.concat(first, second)
Floats.concat(first, second)
źródło
Możesz dołączyć dwie tablice w dwóch wierszach kodu.
Jest to szybkie i wydajne rozwiązanie, które będzie działać na prymitywne typy, a obie metody są przeciążone.
Należy unikać rozwiązań obejmujących ArrayLists, strumienie itp., Ponieważ będą one musiały przydzielić pamięć tymczasową bez żadnego użytecznego celu.
Należy unikać
for
pętli dla dużych tablic, ponieważ nie są one wydajne. Wbudowane metody wykorzystują funkcje szybkiego kopiowania bloków.źródło
Korzystanie z Java API:
źródło
both.toArray(new String[0])
będzie szybsze niżboth.toArray(new String[both.size()])
, nawet jeśli przeczy naszej naiwnej intuicji. Dlatego tak ważne jest, aby zmierzyć rzeczywistą wydajność podczas optymalizacji. Lub po prostu użyj prostszej konstrukcji, gdy nie można udowodnić przewagi bardziej złożonego wariantu.Rozwiązanie w 100% stare java i bez
System.arraycopy
(niedostępne na przykład w kliencie GWT):źródło
null
czeki. I być może ustaw niektóre z twoich zmiennych nafinal
.null
sprawdza raczej ukrywanie NPE niż ich pokazywanie, a używanie finału dla lokalnych zmiennych nie ma jeszcze żadnych korzyści (jeszcze).Ostatnio walczyłem z problemami z nadmierną rotacją pamięci. Jeśli wiadomo, że a i / lub b są zwykle puste, oto kolejna adaptacja kodu silvertab (również wygenerowanego):
Edycja: W poprzedniej wersji tego postu stwierdzono, że takie ponowne użycie tablicy powinno być wyraźnie udokumentowane. Jak zauważa Maarten w komentarzach, ogólnie lepiej byłoby po prostu usunąć stwierdzenia if, tym samym unieważniając potrzebę posiadania dokumentacji. Ale z drugiej strony te instrukcje if były przede wszystkim celem tej konkretnej optymalizacji. Zostawię tę odpowiedź tutaj, ale bądź ostrożny!
źródło
System.arraycopy
kopiuje zawartość tablicy?if
Najprostszym rozwiązaniem byłoby pominięcie dwóch stwierdzeń.Biblioteka funkcjonalna Java ma klasę otoki tablic, która wyposaża tablice w przydatne metody, takie jak konkatenacja.
...i wtedy
Aby odzyskać nieopakowaną tablicę, zadzwoń
źródło
źródło
both.toArray(new String[both.size()])
)Kolejny sposób z Java8 za pomocą Stream
źródło
Oto adaptacja rozwiązania silvertab, z doposażonymi lekami generycznymi:
UWAGA: Zobacz odpowiedź Joachima na rozwiązanie Java 6. Nie tylko eliminuje to ostrzeżenie; jest również krótszy, wydajniejszy i łatwiejszy do odczytania!
źródło
Jeśli korzystasz z tej metody, nie musisz importować żadnych klas stron trzecich.
Jeśli chcesz konkatenować
String
Przykładowy kod dla concate two String Array
Jeśli chcesz konkatenować
Int
Przykładowy kod dla concate two Integer Array
Oto główna metoda
Z tego też możemy korzystać.
źródło
Proszę wybaczyć, że dodałem kolejną wersję do tej i tak już długiej listy. Przejrzałem każdą odpowiedź i zdecydowałem, że naprawdę chcę wersję z jednym parametrem w podpisie. Dodałem także pewne sprawdzanie argumentów, aby skorzystać z wczesnego niepowodzenia z sensownymi informacjami w przypadku nieoczekiwanego wejścia.
źródło
Możesz spróbować przekonwertować go na Arraylist i użyć metody addAll, a następnie przekonwertować z powrotem na tablicę.
źródło
Za pomocą strumieni Java 8+ możesz napisać następującą funkcję:
źródło
Tutaj możliwa implementacja w działającym kodzie rozwiązania pseudokodu napisanego przez silvertab.
Dzięki silvertab!
Następny jest interfejs konstruktora.
Uwaga: Konstruktor jest konieczny, ponieważ w Javie nie jest to możliwe
new T[size]
z powodu ogólnego usunięcia typu:
Oto konkretny konstruktor implementujący interfejs, budujący
Integer
tablicę:I na koniec aplikacja / test:
źródło
To powinno być jedno-liniowe.
źródło
Łał! wiele skomplikowanych odpowiedzi tutaj, w tym kilka prostych, które zależą od zewnętrznych zależności. co powiesz na zrobienie tego w ten sposób:
źródło
To działa, ale musisz wstawić własne sprawdzanie błędów.
Prawdopodobnie nie jest to najbardziej wydajny, ale nie opiera się na niczym innym niż własny interfejs API Java.
źródło
for
pętlę na:for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)
aby pominąć pierwsząfor
pętlę. Oszczędza czas proporcjonalny do wielkościarr1
.To jest przekonwertowana funkcja dla tablicy String:
źródło
A może po prostu
I po prostu zrób
Array.concat(arr1, arr2)
. Dopóki sąarr1
iarr2
są tego samego typu, daje to kolejną tablicę tego samego typu zawierającą obie tablice.źródło
Ogólna wersja statyczna, która wykorzystuje wysoce wydajny System.arraycopy bez wymagania adnotacji @SuppressWarnings:
źródło
źródło
Oto moja nieznacznie ulepszona wersja concatAll Joachima Sauera. Może pracować na Javie 5 lub 6, używając System.arraycopy Java 6, jeśli jest dostępny w czasie wykonywania. Ta metoda (IMHO) jest idealna dla Androida, ponieważ działa na Androidzie <9 (który nie ma System.arraycopy), ale w miarę możliwości zastosuje szybszą metodę.
źródło
Inny sposób myślenia o pytaniu. Aby połączyć dwie lub więcej tablic, wystarczy zrobić listę wszystkich elementów każdej z tablic, a następnie zbudować nową tablicę. To brzmi jak utwórz
List<T>
a następnie wywołujetoArray
. Używasz innych odpowiedziArrayList
i to jest w porządku. Ale co powiesz na wdrożenie naszego własnego? To nie jest trudne:Uważam, że powyższe jest równoważne rozwiązaniom, które wykorzystują
System.arraycopy
. Myślę jednak, że ten ma swoje piękno.źródło
Co powiesz na :
źródło
Prosta odmiana umożliwiająca połączenie więcej niż jednej tablicy:
źródło
Używanie tylko własnego interfejsu API języka JavaScript:
Teraz ten kod nie jest najbardziej wydajny, ale opiera się tylko na standardowych klasach Java i jest łatwy do zrozumienia. Działa dla dowolnej liczby String [] (nawet zerowych tablic).
źródło