Come posso concatenare due array in Java?

Ho bisogno di concatenare due array di stringhe in Java.

void f(String[] first, String[] second) { String[] both = ??? } 

Qual è il modo più semplice per farlo?

Ho trovato una soluzione a una riga dalla buona vecchia libreria di Apache Commons Lang.
ArrayUtils.addAll(T[], T...)

Codice:

 String[] both = (String[])ArrayUtils.addAll(first, second); 

Ecco un semplice metodo che concatenerà due array e restituirà il risultato:

 public  T[] concatenate(T[] a, T[] b) { int aLen = a.length; int bLen = b.length; @SuppressWarnings("unchecked") T[] c = (T[]) Array.newInstance(a.getClass().getComponentType(), aLen + bLen); System.arraycopy(a, 0, c, 0, aLen); System.arraycopy(b, 0, c, aLen, bLen); return c; } 

Nota come non funzionerà con i primitivi, solo con i tipi di object.

La seguente versione leggermente più complicata funziona sia con gli oggetti che con gli array primitivi. Lo fa usando T invece di T[] come tipo di argomento.

Consente inoltre di concatenare matrici di due tipi diversi selezionando il tipo più generale come tipo di componente del risultato.

 public static  T concatenate(T a, T b) { if (!a.getClass().isArray() || !b.getClass().isArray()) { throw new IllegalArgumentException(); } Class resCompType; Class aCompType = a.getClass().getComponentType(); Class bCompType = b.getClass().getComponentType(); if (aCompType.isAssignableFrom(bCompType)) { resCompType = aCompType; } else if (bCompType.isAssignableFrom(aCompType)) { resCompType = bCompType; } else { throw new IllegalArgumentException(); } int aLen = Array.getLength(a); int bLen = Array.getLength(b); @SuppressWarnings("unchecked") T result = (T) Array.newInstance(resCompType, aLen + bLen); System.arraycopy(a, 0, result, 0, aLen); System.arraycopy(b, 0, result, aLen, bLen); return result; } 

Ecco un esempio:

 Assert.assertArrayEquals(new int[] { 1, 2, 3 }, concatenate(new int[] { 1, 2 }, new int[] { 3 })); Assert.assertArrayEquals(new Number[] { 1, 2, 3f }, concatenate(new Integer[] { 1, 2 }, new Number[] { 3f })); 

È ansible scrivere una versione completamente generica che può anche essere estesa per concatenare un numero qualsiasi di array. Queste versioni richiedono Java 6, poiché usano Arrays.copyOf()

Entrambe le versioni evitano di creare oggetti List intermedi e utilizzano System.arraycopy() per garantire che la copia di array di grandi dimensioni sia la più veloce ansible.

Per due array, è come questo:

 public static  T[] concat(T[] first, T[] second) { T[] result = Arrays.copyOf(first, first.length + second.length); System.arraycopy(second, 0, result, first.length, second.length); return result; } 

E per un numero arbitrario di matrici (> = 1) appare come questo:

 public static  T[] concatAll(T[] first, T[]... rest) { int totalLength = first.length; for (T[] array : rest) { totalLength += array.length; } T[] result = Arrays.copyOf(first, totalLength); int offset = first.length; for (T[] array : rest) { System.arraycopy(array, 0, result, offset, array.length); offset += array.length; } return result; } 

One-liner in Java 8:

 String[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)) .toArray(String[]::new); 

O:

 String[] both = Stream.of(a, b).flatMap(Stream::of) .toArray(String[]::new); 

O con l’amato Guava :

 String[] both = ObjectArrays.concat(first, second, String.class); 

Inoltre, ci sono versioni per gli array primitivi:

  • 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)

Utilizzo dell’API Java:

 String[] f(String[] first, String[] second) { List both = new ArrayList(first.length + second.length); Collections.addAll(both, first); Collections.addAll(both, second); return both.toArray(new String[both.size()]); } 

Una soluzione java al 100% vecchia e senza System.arraycopy (non disponibile nel client GWT, ad esempio):

 static String[] concat(String[]... arrays) { int length = 0; for (String[] array : arrays) { length += array.length; } String[] result = new String[length]; int pos = 0; for (String[] array : arrays) { for (String element : array) { result[pos] = element; pos++; } } return result; } 

Recentemente ho combattuto problemi con un’eccessiva rotazione della memoria. Se a e / o b sono noti per essere comunemente vuoti, ecco un altro adattamento del codice di silvertab (anch’esso generato):

 private static  T[] concat(T[] a, T[] b) { final int alen = a.length; final int blen = b.length; if (alen == 0) { return b; } if (blen == 0) { return a; } final T[] result = (T[]) java.lang.reflect.Array. newInstance(a.getClass().getComponentType(), alen + blen); System.arraycopy(a, 0, result, 0, alen); System.arraycopy(b, 0, result, alen, blen); return result; } 

(In entrambi i casi, il comportamento di riutilizzo dell’array deve essere chiaramente JavaDoced!)

La libreria Java funzionale ha una class wrapper di array che equipaggia gli array con metodi pratici come la concatenazione.

 import static fj.data.Array.array; 

…e poi

 Array both = array(first).append(array(second)); 

Per richiamare l’array scartato, chiama

 String[] s = both.array(); 
 ArrayList both = new ArrayList(Arrays.asList(first)); both.addAll(Arrays.asList(second)); both.toArray(new String[0]); 

Ecco un adattamento della soluzione di silvertab, con i generici adattati:

 static  T[] concat(T[] a, T[] b) { final int alen = a.length; final int blen = b.length; final T[] result = (T[]) java.lang.reflect.Array. newInstance(a.getClass().getComponentType(), alen + blen); System.arraycopy(a, 0, result, 0, alen); System.arraycopy(b, 0, result, alen, blen); return result; } 

NOTA: vedi la risposta di Joachim per una soluzione Java 6. Non solo elimina l’avvertimento; è anche più breve, più efficiente e più facile da leggere!

Un altro modo con Java8 usando Stream

  public String[] concatString(String[] a, String[] b){ Stream streamA = Arrays.stream(a); Stream streamB = Arrays.stream(b); return Stream.concat(streamA, streamB).toArray(String[]::new); } 

È ansible aggiungere i due array in due righe di codice.

 String[] both = Arrays.copyOf(first, first.length + second.length); System.arraycopy(second, 0, both, first.length, second.length); 

Questa è una soluzione rapida ed efficiente e funzionerà per i tipi primitivi, così come i due metodi coinvolti sono sovraccarichi.

È necessario evitare soluzioni che coinvolgono ArrayList, flussi, ecc. Poiché questi dovranno allocare memoria temporanea per scopi non utili.

Dovresti evitare i loop perché questi non sono efficienti. I metodi incorporati utilizzano funzioni di copia di blocchi estremamente veloci.

Se si utilizza in questo modo, non è necessario importare classi di terze parti.

Se vuoi concatenare String

Esempio di codice per conciliare due array di stringhe

 public static String[] combineString(String[] first, String[] second){ int length = first.length + second.length; String[] result = new String[length]; System.arraycopy(first, 0, result, 0, first.length); System.arraycopy(second, 0, result, first.length, second.length); return result; } 

Se vuoi concatenare Int

Esempio di codice per conciliare due array Integer

 public static int[] combineInt(int[] a, int[] b){ int length = a.length + b.length; int[] result = new int[length]; System.arraycopy(a, 0, result, 0, a.length); System.arraycopy(b, 0, result, a.length, b.length); return result; } 

Ecco il metodo principale

  public static void main(String[] args) { String [] first = {"a", "b", "c"}; String [] second = {"d", "e"}; String [] joined = combineString(first, second); System.out.println("concatenated String array : " + Arrays.toString(joined)); int[] array1 = {101,102,103,104}; int[] array2 = {105,106,107,108}; int[] concatenateInt = combineInt(array1, array2); System.out.println("concatenated Int array : " + Arrays.toString(concatenateInt)); } } 

Possiamo usare anche in questo modo.

Per favore perdonami per aver aggiunto ancora un’altra versione a questa già lunga lista. Ho guardato ogni risposta e ho deciso che volevo davvero una versione con un solo parametro nella firma. Ho anche aggiunto alcuni argomenti per trarre vantaggio da un errore precoce con informazioni sensibili in caso di input imprevisti.

 @SuppressWarnings("unchecked") public static  T[] concat(T[]... inputArrays) { if(inputArrays.length < 2) { throw new IllegalArgumentException("inputArrays must contain at least 2 arrays"); } for(int i = 0; i < inputArrays.length; i++) { if(inputArrays[i] == null) { throw new IllegalArgumentException("inputArrays[" + i + "] is null"); } } int totalLength = 0; for(T[] array : inputArrays) { totalLength += array.length; } T[] result = (T[]) Array.newInstance(inputArrays[0].getClass().getComponentType(), totalLength); int offset = 0; for(T[] array : inputArrays) { System.arraycopy(array, 0, result, offset, array.length); offset += array.length; } return result; } 

Potresti provare a convertirlo in un Arraylist e usare il metodo addAll per poi riconvertirlo in un array.

 List list = new ArrayList(Arrays.asList(first)); list.addAll(Arrays.asList(second)); String[] both = list.toArray(); 

Ecco una ansible implementazione nel codice di lavoro della soluzione di pseudo codice scritta da silvertab.

Grazie silvertab!

 public class Array { public static  T[] concat(T[] a, T[] b, ArrayBuilderI builder) { T[] c = builder.build(a.length + b.length); System.arraycopy(a, 0, c, 0, a.length); System.arraycopy(b, 0, c, a.length, b.length); return c; } } 

Di seguito è l’interfaccia del costruttore.

Nota: un builder è necessario perché in java non è ansible farlo

new T[size]

a causa della cancellazione di tipo generico:

 public interface ArrayBuilderI { public T[] build(int size); } 

Qui un costruttore concreto che implementa l’interfaccia, costruendo un array Integer :

 public class IntegerArrayBuilder implements ArrayBuilderI { @Override public Integer[] build(int size) { return new Integer[size]; } } 

E infine l’applicazione / test:

 @Test public class ArrayTest { public void array_concatenation() { Integer a[] = new Integer[]{0,1}; Integer b[] = new Integer[]{2,3}; Integer c[] = Array.concat(a, b, new IntegerArrayBuilder()); assertEquals(4, c.length); assertEquals(0, (int)c[0]); assertEquals(1, (int)c[1]); assertEquals(2, (int)c[2]); assertEquals(3, (int)c[3]); } } 

Wow! molte risposte complesse qui incluse alcune semplici che dipendono da dipendenze esterne. che ne dici di farlo in questo modo:

 String [] arg1 = new String{"a","b","c"}; String [] arg2 = new String{"x","y","z"}; ArrayList temp = new ArrayList(); temp.addAll(Arrays.asList(arg1)); temp.addAll(Arrays.asList(arg2)); String [] concatedArgs = temp.toArray(new String[arg1.length+arg2.length]); 

Questa è una funzione convertita per un array di stringhe:

 public String[] mergeArrays(String[] mainArray, String[] addArray) { String[] finalArray = new String[mainArray.length + addArray.length]; System.arraycopy(mainArray, 0, finalArray, 0, mainArray.length); System.arraycopy(addArray, 0, finalArray, mainArray.length, addArray.length); return finalArray; } 

Che ne dici di semplicemente

 public static class Array { public static  T[] concat(T[]... arrays) { ArrayList al = new ArrayList(); for (T[] one : arrays) Collections.addAll(al, one); return (T[]) al.toArray(arrays[0].clone()); } } 

E fai semplicemente Array.concat(arr1, arr2) . Finché arr1 e arr2 sono dello stesso tipo, questo ti darà un altro array dello stesso tipo contenente entrambi gli array.

Funziona, ma è necessario inserire il proprio controllo degli errori.

 public class StringConcatenate { public static void main(String[] args){ // Create two arrays to concatenate and one array to hold both String[] arr1 = new String[]{"s","t","r","i","n","g"}; String[] arr2 = new String[]{"s","t","r","i","n","g"}; String[] arrBoth = new String[arr1.length+arr2.length]; // Copy elements from first array into first part of new array for(int i = 0; i < arr1.length; i++){ arrBoth[i] = arr1[i]; } // Copy elements from second array into last part of new array for(int j = arr1.length;j < arrBoth.length;j++){ arrBoth[j] = arr2[j-arr1.length]; } // Print result for(int k = 0; k < arrBoth.length; k++){ System.out.print(arrBoth[k]); } // Additional line to make your terminal look better at completion! System.out.println(); } } 

Probabilmente non è il più efficiente, ma non si basa su nulla di diverso dall'API di Java.

Ecco la mia versione leggermente migliorata di concatAll di Joachim Sauer. Può funzionare su Java 5 o 6, utilizzando System.arraycopy di Java 6 se è disponibile in fase di runtime. Questo metodo (IMHO) è perfetto per Android, poiché funziona su Android <9 (che non ha System.arraycopy) ma utilizzerà il metodo più veloce se possibile.

  public static  T[] concatAll(T[] first, T[]... rest) { int totalLength = first.length; for (T[] array : rest) { totalLength += array.length; } T[] result; try { Method arraysCopyOf = Arrays.class.getMethod("copyOf", Object[].class, int.class); result = (T[]) arraysCopyOf.invoke(null, first, totalLength); } catch (Exception e){ //Java 6 / Android >= 9 way didn't work, so use the "traditional" approach result = (T[]) java.lang.reflect.Array.newInstance(first.getClass().getComponentType(), totalLength); System.arraycopy(first, 0, result, 0, first.length); } int offset = first.length; for (T[] array : rest) { System.arraycopy(array, 0, result, offset, array.length); offset += array.length; } return result; } 

Un altro modo di pensare alla domanda. Per concatenare due o più matrici, è necessario elencare tutti gli elementi di ciascun array e quindi creare un nuovo array. Questo suona come creare un List e quindi chiama toArray su di esso. Altre risposte usano ArrayList , e va bene. Ma come implementare il nostro? Non è difficile:

 private static  T[] addAll(final T[] f, final T...o){ return new AbstractList(){ @Override public T get(int i) { return i>=f.length ? o[i - f.length] : f[i]; } @Override public int size() { return f.length + o.length; } }.toArray(f); } 

Credo che quanto sopra sia equivalente alle soluzioni che utilizzano System.arraycopy . Comunque penso che questo abbia la sua bellezza.

Che ne dite di :

 public String[] combineArray (String[] ... strings) { List tmpList = new ArrayList(); for (int i = 0; i < strings.length; i++) tmpList.addAll(Arrays.asList(strings[i])); return tmpList.toArray(new String[tmpList.size()]); } 

Una semplice variazione che consente l’unione di più di un array:

 public static String[] join(String[]...arrays) { final List output = new ArrayList(); for(String[] array : arrays) { output.addAll(Arrays.asList(array)); } return output.toArray(new String[output.size()]); } 

Utilizzando solo l’API di Javas:

 String[] join(String[]... arrays) { // calculate size of target array int size = 0; for (String[] array : arrays) { size += array.length; } // create list of appropriate size java.util.List list = new java.util.ArrayList(size); // add arrays for (String[] array : arrays) { list.addAll(java.util.Arrays.asList(array)); } // create and return final array return list.toArray(new String[size]); } 

Ora, questo codice non è il più efficiente, ma si basa solo su classi Java standard ed è facile da capire. Funziona per qualsiasi numero di String [] (anche zero array).

Un modo facile, ma inefficiente, per farlo (generici non inclusi):

 ArrayList baseArray = new ArrayList(Arrays.asList(array1)); baseArray.addAll(Arrays.asList(array2)); String concatenated[] = (String []) baseArray.toArray(new String[baseArray.size()]); 
 public String[] concat(String[]... arrays) { int length = 0; for (String[] array : arrays) { length += array.length; } String[] result = new String[length]; int destPos = 0; for (String[] array : arrays) { System.arraycopy(array, 0, result, destPos, array.length); destPos += array.length; } return result; } 
 String [] both = new ArrayList(){{addAll(Arrays.asList(first)); addAll(Arrays.asList(second));}}.toArray(new String[0]); 

Una variazione di tipo indipendente (AGGIORNATA – grazie a Volley per l’istanziazione di T):

 @SuppressWarnings("unchecked") public static  T[] join(T[]...arrays) { final List output = new ArrayList(); for(T[] array : arrays) { output.addAll(Arrays.asList(array)); } return output.toArray((T[])Array.newInstance( arrays[0].getClass().getComponentType(), output.size())); }