Come posso concatenare due array in Java?


1366

Devo concatenare due Stringarray in Java.

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

Qual è il modo più semplice per farlo?


3
Bytes.concat da Guava
Ben Pagina

1
Vedo molte risposte qui, ma la domanda è così formulata ("modo più semplice"?) Che non consente di indicare la risposta migliore ...
Artur Opalinski,

2
Dozzine di risposte qui stanno copiando i dati in un nuovo array perché è quello che è stato richiesto - ma copiare i dati quando non strettamente necessari è una cosa negativa da fare soprattutto in Java. Tieni invece traccia degli indici e usa i due array come se fossero uniti. Ho aggiunto una soluzione che illustra la tecnica.
Douglas tenuto il

12
Il fatto che una domanda come questa abbia attualmente 50 risposte diverse mi fa chiedere perché Java non abbia mai ottenuto una semplice array1 + array2concatenazione.
JollyJoker,

2
Puoi farlo perfettamente e in modo molto efficiente in due righe di Java standard (vedi la mia risposta), quindi non c'è molto da guadagnare avendo un solo metodo per farlo. Tutte queste soluzioni strane e meravigliose sono un po 'una perdita di tempo.
rghome,

Risposte:


1093

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

Codice:

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

175
In che modo "tradisce" se risponde alla domanda? Certo, avere una dipendenza extra è probabilmente eccessivo per questa situazione specifica, ma non viene fatto alcun danno nel dichiarare che esiste, specialmente perché ci sono così tante eccellenti funzionalità in Apache Commons.
Rob,

33
Sono d'accordo, questo non risponde davvero alla domanda. Le librerie di alto livello possono essere fantastiche, ma se vuoi imparare un modo efficiente per farlo, vuoi guardare il codice che il metodo di libreria sta usando. Inoltre, in molte situazioni, non è possibile passare al volo attraverso un'altra libreria del prodotto.
AdamC,

76
Penso che questa sia una buona risposta. Sono state fornite anche soluzioni POJO, ma se l'OP sta già utilizzando Apache Commons nel loro programma (del tutto possibile considerando la sua popolarità), potrebbe ancora non conoscere questa soluzione. Quindi non "aggiungerebbe una dipendenza per questo metodo", ma farebbe un uso migliore di una libreria esistente.
Adam,

14
Se sei sempre preoccupato di non aggiungere una libreria per un singolo metodo, non verranno mai aggiunte nuove librerie. Date le eccellenti utility presenti in Apache Commons, consiglio vivamente di aggiungerlo al primo utilizzo.
Hindol,

6
l'uso di Apache Commons non dovrebbe mai essere chiamato "imbroglione". Metto in dubbio la sanità mentale degli sviluppatori che considerano una dipendenza non necessaria.
Jeryl Cook,

768

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

public <T> 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;
}

Si noti che non funzionerà con tipi di dati primitivi, ma solo con tipi di oggetto.

La seguente versione leggermente più complicata funziona con matrici di oggetti e primitive. Lo fa usando Tinvece T[]come tipo di argomento.

Inoltre, consente di concatenare matrici di due tipi diversi selezionando il tipo più generale come tipo di componente del risultato.

public static <T> 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 }));

1
Mi piace questo suggerimento poiché è meno dipendente dalle ultime versioni di Java. Nei miei progetti sono spesso bloccato utilizzando versioni precedenti di profili Java o CLDC in cui alcune delle strutture come quelle menzionate da Antti non sono disponibili.
kvn,

4
La seguente riga interromperà la parte generica: concatenare (nuova stringa [] {"1"}, nuovo oggetto [] {nuovo oggetto ()})
dragon66,

sarebbe bello non dover usare l'annotazione @SuppressWarnings - posterò una soluzione per quello qui sotto.
beaudet,

+1 per Array.newInstance(a.getClass().getComponentType(), aLen + bLen);. Sorprendentemente non l'ho mai visto prima. @beaudet Penso che l'annotazione vada bene qui, considerando il motivo per cui viene soppressa.
Blake,

1
ah, chiamami purista ma preferisco un codice pulito che non richiede la soppressione degli avvisi per rimuovere gli avvisi
beaudet,

475

È possibile scrivere una versione completamente generica che può anche essere estesa per concatenare un numero qualsiasi di matrici. Queste versioni richiedono Java 6, in quanto utilizzanoArrays.copyOf()

Entrambe le versioni evitano di creare Listoggetti intermedi e lo utilizzano System.arraycopy()per garantire che la copia di array di grandi dimensioni sia il più rapida possibile.

Per due array si presenta così:

public static <T> 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 array (> = 1) è simile al seguente:

public static <T> 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;
}

10
@djBO: per le matrici di tipo primitivo dovresti creare un sovraccarico per ogni tipo: basta copiare il codice e sostituirlo Tcon byte(e perdere il <T>).
Joachim Sauer,

puoi dirmi come usare il tipo di operatore <T> nella mia classe?
Johnydep,

6
Aggiungerei questo all'inizio, solo per essere sulla difensiva. if (first == null) {if (second == null) {return null; } ritorno secondo; } if (second == null) {return first; }
maratona,

4
@djBo: che dire di:ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
Sam Goldberg,

18
C'è un bug in questo approccio che diventa evidente se si invocano queste funzioni con array di diversi tipi di componenti, ad esempio concat(ai, ad)dove si aitrova Integer[]ed adè Double[]. (In questo caso, il parametro type <T>viene risolto <? extends Number>dal compilatore.) L'array creato da Arrays.copyOfavrà il tipo di componente del primo array, ovvero Integerin questo esempio. Quando la funzione sta per copiare il secondo array, ArrayStoreExceptionverrà lanciato un. La soluzione è avere un Class<T> typeparametro aggiuntivo .
T-Bull,

457

Utilizzando Streamin Java 8:

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

O in questo modo, usando flatMap:

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

Per fare questo per un tipo generico devi usare la riflessione:

@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
    size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));

28
Quanto è efficiente questo?
Supuhstar

8
Vale la pena leggere: jaxenter.com/… tl; dr - stream potrebbe essere performante o no, dipende da cosa ci fai con loro e dai vincoli del problema (non è sempre questa la risposta? Lol)
Trevor Brown

6
Inoltre, se a o b sono matrici di tipi primitivi, i loro flussi dovranno essere .boxed()tali da essere di tipo Streampiuttosto che ad esempio IntStreamche non possono essere passati come parametro a Stream.concat.
Will Hardwick-Smith il

17
@Will Hardwick-Smith: no, devi solo scegliere la giusta classe di streaming, ad es. Se ae lo bsono int[], usaint[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
Holger il

3
@Supuhstar: probabilmente non è veloce come System.arrayCopy. Ma neanche particolarmente lento. Probabilmente fare questo un molto molte volte con enormi array in realtà contesti sensibili alle prestazioni, per la differenza di tempo di esecuzione alla materia.
Lii,

191

O con l'amata Guava :

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

Inoltre, ci sono versioni per 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)

Per quanto adoro la Guava, il metodo di Apache Commons si occupa meglio di nullable.
Ravi Wallau,

7
Sebbene sia utile utilizzare le librerie, è un peccato che il problema sia stato eliminato. Pertanto la soluzione sottostante rimane inafferrabile.
user924272

51
Qual è il problema con l'astrazione? Non so quale sia il problema di reinventare la ruota qui, se vuoi imparare il problema controlla la fonte o leggi su di essa. Il codice professionale dovrebbe utilizzare librerie di alto livello, molto meglio se sviluppato all'interno di Google!
Breno Salgado,

@RaviWallau Potresti collegarti alla classe che lo fa?
Sébastien Tromp,

1
@ SébastienTromp È la soluzione migliore per questa domanda: ArrayUtils.
Ravi Wallau

70

È possibile aggiungere le due matrici 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 tipi primitivi e i due metodi coinvolti sono sovraccarichi.

È necessario evitare soluzioni che coinvolgono ArrayList, stream, ecc. In quanto dovranno allocare memoria temporanea senza uno scopo utile.

È necessario evitare forloop per array di grandi dimensioni poiché questi non sono efficienti. I metodi integrati utilizzano funzioni di copia a blocchi estremamente veloci.


1
Questa è una delle migliori soluzioni. Java standard al 100%. Veloce / efficiente. Dovrebbero ottenere più voti!
Shebla Tsama,

58

Utilizzando l'API Java:

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

13
Semplicemente, ma inefficiente in quanto crea un array per ArrayList e quindi ne genera un altro per il metodo toArray. Ma è ancora valido in quanto è semplice da leggere.
PhoneixS

1
applicabile per stringhe e oggetti (come richiesto dalla domanda), ma non esiste alcun metodo addAll per i tipi primari (come
ints

Come elaborato in questo articolo , l'uso both.toArray(new String[0])sarà più veloce di both.toArray(new String[both.size()]), anche se contraddice la nostra ingenua intuizione. Ecco perché è così importante misurare le prestazioni effettive durante l'ottimizzazione. O semplicemente usa il costrutto più semplice, quando il vantaggio della variante più complicata non può essere dimostrato.
Holger,

42

Una soluzione java al 100% e senza System.arraycopy (non disponibile nel client GWT per 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;
}

rielaborato il mio per File [], ma è lo stesso. Grazie per la soluzione
ShadowFlame,

5
Probabilmente abbastanza inefficiente però.
JonasCz - Ripristina Monica l'

Potresti voler aggiungere degli nullassegni. E forse imposta alcune delle tue variabili su final.
Tripp Kinetics,

I nullcontrolli di @TrippKinetics nascondono gli NPE anziché mostrarli e l'utilizzo di final per i var locali non ha alcun vantaggio (ancora).
Maarten Bodewes,

1
@Maarten Bodewes Penso che scoprirai (se lo confronti, che ho) che il for-each viene eseguito contemporaneamente al ciclo indicizzato nelle versioni successive di Java. L'ottimizzatore se ne occupa.
rome

33

Di recente ho combattuto i problemi con l'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> T[] concatOrReturnSame(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;
}

Modifica: una versione precedente di questo post affermava che il riutilizzo dell'array come questo deve essere chiaramente documentato. Come sottolinea Maarten nei commenti, in generale sarebbe meglio rimuovere le dichiarazioni if, annullando così la necessità di disporre di documentazione. Ma ancora una volta, quelle dichiarazioni if ​​erano il punto centrale di questa particolare ottimizzazione in primo luogo. Lascio qui questa risposta, ma fai attenzione!


5
ciò significa tuttavia che si sta restituendo lo stesso array e che modificando un valore sull'array restituito si modifica il valore nella stessa posizione dell'array di input restituito.
Lorenzo Boccaccia,

Sì, vedi il commento alla fine del mio post sul riutilizzo dell'array. Il sovraccarico di manutenzione imposto da questa soluzione è valso la pena nel nostro caso particolare, ma la copia difensiva dovrebbe probabilmente essere utilizzata nella maggior parte dei casi.
volley

Lorenzo / volley, puoi spiegare quale parte del codice causa il riutilizzo dell'array? Ho pensato di System.arraycopycopiare il contenuto dell'array?
Rosdi Kasim,

4
Un chiamante si aspetterebbe normalmente che una chiamata a concat () restituisca un array appena allocato. Se a o b è nullo, concat () restituirà comunque uno degli array passati in esso. Questo riutilizzo è ciò che potrebbe essere inaspettato. (Sì, l'arraycopy esegue solo la copia. Il riutilizzo proviene dal ritorno di a o b direttamente.)
volley

Il codice dovrebbe essere il più possibile esplicativo. Le persone che leggono il codice non dovrebbero cercare JavaDoc di una funzione chiamata per scoprire che fa una cosa per una particolare condizione e qualcos'altro per un'altra. In breve: generalmente non è possibile risolvere problemi di progettazione come questi con un commento. Lasciare iffuori le due affermazioni sarebbe la soluzione più semplice.
Maarten Bodewes,

27

La libreria Java funzionale ha una classe wrapper di array che fornisce array con metodi utili come la concatenazione.

import static fj.data.Array.array;

...e poi

Array<String> both = array(first).append(array(second));

Per riavere l'array da scartare, chiamare

String[] s = both.array();

27
ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));

both.toArray(new String[0]);

3
La risposta è ottima ma un po 'rotta. Per renderlo perfetto dovresti passare ad Array () un array del tipo che ti serve. Nell'esempio sopra, il codice dovrebbe essere: both.toArray (new String [0]) Vedi: stackoverflow.com/questions/4042434/…
Ronen Rabinovici,

Non so perché questa risposta non sia classificata più in alto ... anche se sembra aver bisogno della modifica suggerita da @RonenRabinovici
drmrbrewer il

4
O meglio, senza allocazione inutile di array di lunghezza zero both.toArray(new String[both.size()])
:;


Ciao @Honza, è possibile fare lo stesso per restituire un array intero primitivo in 3 righe?
jumping_monkey il

18

Un altro modo con Java8 utilizzando Stream

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

17

Ecco un adattamento della soluzione di silvertab, con generici retrofittati:

static <T> 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: vedere la risposta di Joachim per una soluzione Java 6. Non solo elimina l'avvertimento; è anche più breve, più efficiente e più facile da leggere!


Puoi sopprimere l'avviso per questo metodo, ma a parte questo non c'è molto che puoi fare. Array e generici non si mescolano davvero.
Dan Dyer,

3
L'avviso non selezionato può essere eliminato se si utilizza Arrays.copyOf (). Vedi la mia risposta per un'implementazione.
Joachim Sauer,

@SuppressWarnings ("deselezionato")
Mark Renouf,

13

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

Se vuoi concatenare String

Codice di esempio per concare 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

Codice di esempio per concare due numeri interi

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.


11

Per favore, perdonami per aver aggiunto un'altra versione a questo elenco già lungo. Ho guardato ogni risposta e ho deciso che volevo davvero una versione con un solo parametro nella firma. Ho anche aggiunto alcuni argomenti di verifica per trarre vantaggio da guasti precoci con informazioni sensibili in caso di input imprevisti.

@SuppressWarnings("unchecked")
public static <T> 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;
}

Riassumerei la lunghezza nello stesso ciclo in cui stai facendo il tuo controllo nullo - ma questo è davvero un buon riassunto delle altre risposte qui. Credo che gestisca anche tipi intrinseci come "int" senza cambiarli in oggetti Integer, che è davvero l'UNICA ragione per gestirli come array piuttosto che cambiare tutto in ArrayLists. Inoltre il tuo metodo potrebbe prendere 2 array e un parametro (...) in modo che il chiamante sappia che deve passare almeno due array prima di eseguirlo e vedere l'errore, ma ciò complica il codice di looping ....
Bill K

11

Potresti provare a convertirlo in un Arraylist e utilizzare il metodo addAll, quindi riconvertire in un array.

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

Buona soluzione - sarebbe meglio se il codice fosse refactored per evitare del tutto le matrici a favore di ArrayLists, ma questo è al di fuori del controllo della "Risposta" e fino all'interrogatore.
Bill K,

Conto che per funzionare sono necessari 4 oggetti temporanei aggiuntivi.
rghome,

@rghome, almeno non richiede libreria aggiuntiva per implementare un compito così semplice
Farid

9

Utilizzando i flussi Java 8+ è possibile scrivere la seguente funzione:

private static String[] concatArrays(final String[]... arrays) {
    return Arrays.stream(arrays)
         .flatMap(Arrays::stream)
         .toArray(String[]::new);
}

7

Qui una possibile implementazione nel codice di lavoro della soluzione di pseudo codice scritta da silvertab.

Grazie Silvertab!

public class Array {

   public static <T> T[] concat(T[] a, T[] b, ArrayBuilderI<T> 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 è riportata l'interfaccia del builder.

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

new T[size]

a causa della cancellazione di tipo generico:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

Qui un builder concreto che implementa l'interfaccia, costruendo un Integerarray:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

   @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]);
   }
}

7

Questo dovrebbe essere one-liner.

public String [] concatenate (final String array1[], final String array2[])
{
    return Stream.concat(Stream.of(array1), Stream.of(array2)).toArray(String[]::new);
}

6

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<String> temp = new ArrayList<String>();
temp.addAll(Arrays.asList(arg1));
temp.addAll(Arrays.asList(arg2));
String [] concatedArgs = temp.toArray(new String[arg1.length+arg2.length]);

1
..Ma inefficiente e lento.
JonasCz - Ripristina Monica l'

6

Funziona, ma devi inserire il tuo 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 qualcosa di diverso dall'API di Java.


2
+1. Sarebbe meglio sostituire il secondo forloop con quello:for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
bancer

Utilizzare String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)per saltare il primo forloop. Risparmia tempo proporzionale alla dimensione di arr1.
John Meyer,

5

Questa è una funzione convertita per un array String:

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;
}

5

Che ne dici semplicemente

public static class Array {

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

E basta Array.concat(arr1, arr2). Finché arr1e arr2sono dello stesso tipo, questo ti darà un altro array dello stesso tipo contenente entrambi gli array.


Per motivi di prestazioni, pre-calcolare la dimensione finale di ArrayList perché ArrayList, per definizione, alloca un nuovo array e copia i suoi elementi ogni volta che l'array corrente è pieno. Altrimenti andrei dritto per LinkedList che non presenta questo problema
usr-local-ΕΨΗΕΛΩΝ

5

Una versione statica generica che utilizza System.arraycopy ad alte prestazioni senza richiedere un'annotazione @SuppressWarnings:

public static <T> T[] arrayConcat(T[] a, T[] b) {
    T[] both = Arrays.copyOf(a, a.length + b.length);
    System.arraycopy(b, 0, both, a.length, b.length);
    return both;
}

4
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;
}

4

Ecco la mia versione leggermente migliorata del concatAll di Joachim Sauer. Può funzionare su Java 5 o 6, utilizzando System.arraycopy di Java 6 se è disponibile in fase di esecuzione. 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> 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;
  }

1
Buona idea generale, ma a chiunque la stia implementando: preferirei una versione copyOf e non copyOf rispetto a una che fa entrambe le cose a titolo di riflessione.
rektide,

4

Un altro modo di pensare alla domanda. Per concatenare due o più array, è necessario elencare tutti gli elementi di ciascun array e quindi creare un nuovo array. Questo suona come creare un List<T>e quindi lo chiama toArray. Alcune altre risposte usano ArrayList, e va bene. Ma che ne dici di implementare il nostro? Non è difficile:

private static <T> T[] addAll(final T[] f, final T...o){
    return new AbstractList<T>(){

        @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 a soluzioni che utilizza System.arraycopy. Comunque penso che questo abbia una sua bellezza.


4

Che ne dite di :

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

4

Una semplice variante che consente di unire più di un array:

public static String[] join(String[]...arrays) {

    final List<String> output = new ArrayList<String>();

    for(String[] array : arrays) {
        output.addAll(Arrays.asList(array));
    }

    return output.toArray(new String[output.size()]);
}

3

Utilizzando solo l'API propria 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 con qualsiasi numero di String [] (anche zero array).


15
Ho dovuto sottovalutare questo per tutta la creazione non necessaria di oggetti List.
Programmatore fuorilegge il
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.