¿Cómo puedo concatenar dos matrices en Java?

1366

Necesito concatenar dos Stringmatrices en Java.

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

¿Cuál es la forma más fácil de hacer esto?

Antti Kissaniemi
fuente
3
Bytes.concat de Guava
Ben Page
1
Veo muchas respuestas aquí, pero la pregunta está tan redactada (¿'la forma más fácil'?) Que no permite indicar la mejor respuesta ...
Artur Opalinski
2
Docenas de respuestas aquí están copiando los datos en una nueva matriz porque eso es lo que se solicitó, pero copiar datos cuando no es estrictamente necesario es algo malo, especialmente en Java. En su lugar, realice un seguimiento de los índices y use las dos matrices como si estuvieran unidas. He agregado una solución que ilustra la técnica.
Douglas celebrada el
12
El hecho de que una pregunta como esta tenga actualmente 50 respuestas diferentes me hace preguntarme por qué Java nunca obtuvo una array1 + array2concatenación simple .
JollyJoker
2
Puede hacerlo perfectamente bien y de manera muy eficiente en dos líneas de Java estándar (vea mi respuesta), por lo que no hay mucho que ganar al tener un solo método para hacerlo. Todas estas soluciones extrañas y maravillosas son una pérdida de tiempo.
rghome

Respuestas:

1093

Encontré una solución de una línea de la vieja y buena biblioteca Apache Commons Lang.
ArrayUtils.addAll(T[], T...)

Código:

String[] both = ArrayUtils.addAll(first, second);
Antti Kissaniemi
fuente
175
¿Cómo es "hacer trampa" si responde la pregunta? Claro, tener una dependencia adicional es probablemente excesivo para esta situación específica, pero no se hace daño al señalar que existe, especialmente porque hay tantos bits excelentes de funcionalidad en Apache Commons.
Rob
33
Estoy de acuerdo, esto realmente no responde la pregunta. Las bibliotecas de alto nivel pueden ser geniales, pero si quieres aprender una manera eficiente de hacerlo, debes mirar el código que está usando el método de la biblioteca. Además, en muchas situaciones, no puede simplemente pasar por otra biblioteca del producto sobre la marcha.
AdamC
76
Creo que esta es una buena respuesta. También se han proporcionado soluciones POJO, pero si el OP ya está usando Apache Commons en su programa (totalmente posible teniendo en cuenta su popularidad), es posible que aún no conozca esta solución. Entonces no estaría "agregando una dependencia para este método", sino que estaría haciendo un mejor uso de una biblioteca existente.
Adam
14
Si siempre le preocupa no agregar una biblioteca para un solo método, nunca se agregarán nuevas bibliotecas. Dadas las excelentes utilidades presentes en Apache Commons, recomiendo agregarlo cuando surja el primer caso de uso.
Hindol
66
usar apache commons nunca debería llamarse 'trampa'. Cuestiono la cordura de los desarrolladores que consideran que es una dependencia innecesaria.
Jeryl Cook
768

Aquí hay un método simple que concatenará dos matrices y devolverá el resultado:

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

Tenga en cuenta que no funcionará con tipos de datos primitivos, solo con tipos de objetos.

La siguiente versión un poco más complicada funciona con objetos y matrices primitivas. Lo hace utilizando en Tlugar de T[]como el tipo de argumento.

También hace posible concatenar matrices de dos tipos diferentes seleccionando el tipo más general como el tipo de componente del resultado.

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

Aquí hay un ejemplo:

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 }));
Lii
fuente
1
Me gusta esta sugerencia, ya que depende menos de las últimas versiones de Java. En mis proyectos, a menudo estoy atascado usando versiones anteriores de Java o perfiles CLDC donde algunas de las instalaciones como las mencionadas por Antti no están disponibles.
kvn
44
La siguiente línea dividirá la parte genérica: concatenate (new String [] {"1"}, new Object [] {new Object ()})
dragon66
Sería bueno no tener que usar la anotación @SuppressWarnings. Publicaré una solución para eso a continuación.
beaudet
+1 para Array.newInstance(a.getClass().getComponentType(), aLen + bLen);. Sorprendentemente, nunca he visto eso antes. @beaudet Creo que la anotación está bien aquí, considerando por qué está siendo suprimida.
Blake
1
ja, llámame purista, pero prefiero un código limpio que no requiera la supresión de advertencias para eliminar advertencias
beaudet
475

Es posible escribir una versión totalmente genérica que incluso se puede extender para concatenar cualquier número de matrices. Estas versiones requieren Java 6, ya que usanArrays.copyOf()

Ambas versiones evitan crear Listobjetos intermedios y usarSystem.arraycopy() para garantizar que copiar matrices grandes sea lo más rápido posible.

Para dos matrices se ve así:

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

Y para un número arbitrario de matrices (> = 1) se ve así:

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;
}
Joachim Sauer
fuente
10
@djBO: para matrices de tipo primitivo necesitaría hacer una sobrecarga para cada tipo: simplemente copie el código y reemplácelo Tcon byte(y pierda el <T>).
Joachim Sauer
¿puedes decirme cómo usar el tipo de operador <T> en mi clase?
Johnydep
66
Añadiría esto al principio, solo para estar a la defensiva. if (first == null) {if (second == null) {return null; } regresar segundo; } if (segundo == nulo) {regresar primero; }
maratón
44
@djBo: ¿qué pasa con:ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
Sam Goldberg
18
Hay un error en este enfoque que se hace evidente si invoca estas funciones con matrices de diferentes tipos de componentes, por ejemplo concat(ai, ad), dónde aiestá Integer[]y dónde adestá Double[]. (En este caso, el compilador <T>resuelve el parámetro de tipo <? extends Number>). La matriz creada por Arrays.copyOftendrá el tipo de componente de la primera matriz, es decir, Integeren este ejemplo. Cuando la función está a punto de copiar la segunda matriz, se ArrayStoreExceptionlanzará un . La solución es tener un Class<T> typeparámetro adicional .
T-Bull
457

Utilizando Streamen Java 8:

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

O así, usando flatMap:

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

Para hacer esto para un tipo genérico, debe usar la reflexión:

@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
    size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));
Lii
fuente
28
¿Qué tan eficiente es esto?
Supuhstar
8
Vale la pena leerlo: jaxenter.com/… tl; dr - streams puede ser eficaz o no, depende de lo que estés haciendo con ellos y de las limitaciones del problema (¿no es siempre la respuesta? Jajaja)
Trevor Brown
66
Además, si una o b son matrices de tipos primitivos, sus corrientes tendrán que ser .boxed()por lo que son de tipo Streammás bien que por ejemplo, IntStreamque no se pueden pasar como un parámetro a Stream.concat.
Will Hardwick-Smith
17
@Will Hardwick-Smith: no, es suficiente con elegir la clase de secuencia correcta, por ejemplo, si ay bson int[], el usoint[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
Holger
3
@Supuhstar: Probablemente no sea tan rápido como System.arrayCopy. Pero tampoco particularmente lento. Es probable que tenga que hacer esto una muy muchas veces con grandes matrices en realidad contextos sensibles al rendimiento de la diferencia de tiempo de ejecución a la materia.
Lii
191

O con la amada guayaba :

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

Además, hay versiones para matrices primitivas:

  • 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)
KARASZI István
fuente
Por mucho que ame la guayaba, el método de Apache Commons trata mejor con los nulables.
Ravi Wallau el
77
Si bien es bueno usar bibliotecas, es lamentable que el problema se haya resuelto. Por lo tanto, la solución subyacente sigue siendo difícil de alcanzar.
user924272
51
¿Cuál es el problema con la abstracción? No sé cuál es el problema de reinventar la rueda aquí, si quieres aprender el problema, revisa la fuente o sigue leyendo. ¡El código profesional debería usar bibliotecas de alto nivel, mucho mejor si se desarrolla dentro de Google!
Breno Salgado
@RaviWallau ¿Podría vincular a la clase que hace esto?
Sébastien Tromp
1
@ SébastienTromp Es la mejor solución para esta pregunta: ArrayUtils.
Ravi Wallau
70

Puede agregar las dos matrices en dos líneas de código.

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

Esta es una solución rápida y eficiente y funcionará para tipos primitivos, así como los dos métodos involucrados están sobrecargados.

Debe evitar las soluciones que involucran ArrayLists, streams, etc., ya que necesitarán asignar memoria temporal sin ningún propósito útil.

Debe evitar los forbucles para matrices grandes, ya que no son eficientes. Los métodos incorporados utilizan funciones de copia en bloque que son extremadamente rápidas.

rghome
fuente
1
Esta es una de las mejores soluciones. 100% Java estándar. Rápido / eficiente Debería obtener más votos a favor!
Shebla Tsama
58

Usando la API de 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()]);
}
Fabian Steeg
fuente
13
Simplemente, pero ineficiente, ya que crea una matriz para ArrayList y luego genera otra para el método toArray. Pero sigue siendo válido, ya que es fácil de leer.
PhoneixS
1
aplicable para cadenas y objetos (como pregunta quiere), pero no hay un método addAll para tipos primarios (como
ints
Como se detalla en este artículo , el uso both.toArray(new String[0])será más rápido que both.toArray(new String[both.size()]), incluso si contradice nuestra intuición ingenua. Por eso es tan importante medir el rendimiento real al optimizar. O simplemente use la construcción más simple, cuando no se pueda probar la ventaja de la variante más complicada.
Holger
42

Una solución 100% antigua de Java y sin ella System.arraycopy (no disponible en el cliente GWT, por ejemplo):

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;
}
francois
fuente
reelaborado el mío para el archivo [], pero es lo mismo. Gracias por su solución
ShadowFlame
55
Sin embargo, probablemente sea bastante ineficiente.
JonasCz - Restablece a Mónica el
Es posible que desee agregar nullcheques. Y quizás establezca algunas de sus variables en final.
Tripp Kinetics
Las nullcomprobaciones de @TrippKinetics ocultarían los NPE en lugar de mostrarlos y el uso de final para vars locales no tiene ningún beneficio (todavía).
Maarten Bodewes
1
@Maarten Bodewes Creo que encontrará (si lo compara, lo que tengo) que el for-each se ejecuta al mismo tiempo que el bucle indexado en las últimas versiones de Java. El optimizador se encarga de eso.
rghome
33

Recientemente he luchado contra problemas con la rotación excesiva de memoria. Si se sabe que ayb están comúnmente vacíos, aquí hay otra adaptación del código de silvertab (también generado):

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

Editar: una versión anterior de esta publicación declaró que la reutilización de matrices como esta debe documentarse claramente. Como señala Maarten en los comentarios, en general sería mejor simplemente eliminar las declaraciones if, anulando así la necesidad de tener documentación. Pero, de nuevo, esas declaraciones if fueron el punto central de esta optimización particular en primer lugar. Dejaré esta respuesta aquí, ¡pero ten cuidado!

volley
fuente
55
Sin embargo, esto significa que está devolviendo la misma matriz y cambiar un valor en la matriz devuelta cambia el valor en la misma posición de la matriz de entrada devuelta.
Lorenzo Boccaccia el
Sí, vea el comentario al final de mi publicación sobre la reutilización de la matriz. La sobrecarga de mantenimiento impuesta por esta solución valió la pena en nuestro caso particular, pero la copia defensiva probablemente debería usarse en la mayoría de los casos.
volley
Lorenzo / volley, ¿puedes explicar qué parte del código causa la reutilización de la matriz? Pensé que System.arraycopycopia el contenido de la matriz?
Rosdi Kasim
44
Una persona que llama normalmente esperaría una llamada a concat () para devolver una matriz recién asignada. Si aob es nulo, sin embargo, concat () devolverá una de las matrices que se le pasaron. Esta reutilización es lo que puede ser inesperado. (Sí, arraycopy solo copia. La reutilización proviene de devolver aob directamente.)
volea
El código debe ser tan explicativo como sea posible. Las personas que leen el código no deberían tener que buscar el JavaDoc de una función llamada para descubrir que hace una cosa para una condición particular y otra para otra. En resumen: generalmente no puede solucionar problemas de diseño como estos con un comentario. Simplemente dejar las dos ifdeclaraciones fuera sería la solución más fácil.
Maarten Bodewes
27

La biblioteca funcional de Java tiene una clase de envoltorio de matriz que equipa las matrices con métodos útiles como la concatenación.

import static fj.data.Array.array;

...y entonces

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

Para recuperar la matriz desenvuelta, llame a

String[] s = both.array();
Apocalisp
fuente
27
ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));

both.toArray(new String[0]);
nick-s
fuente
3
La respuesta es genial, pero un poco rota. Para hacerlo perfecto, debe pasar a toArray () una matriz del tipo que necesita. En el ejemplo anterior, el código debe ser: both.toArray (cadena nueva [0]) Ver: stackoverflow.com/questions/4042434/…
Ronen Rabinovici
No sé por qué esta respuesta no tiene una calificación más alta ... aunque parece necesitar el cambio sugerido por @RonenRabinovici
drmrbrewer
44
O mejor, sin una asignación innecesaria de la matriz de longitud cero both.toArray(new String[both.size()])
:;
1
@Honza recomienda leer
Holger
Hola @Honza, ¿es posible hacer lo mismo para devolver una matriz entera primitiva en 3 líneas?
jumping_monkey
18

Otra forma con Java8 usando 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); 
  }
Vaseph
fuente
17

Aquí hay una adaptación de la solución de silvertab, con genéricos reacondicionados:

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: Vea la respuesta de Joachim para una solución Java 6. No solo elimina la advertencia; ¡también es más corto, más eficiente y más fácil de leer!

volley
fuente
Puede suprimir la advertencia para este método, pero aparte de eso, no hay mucho que pueda hacer. Las matrices y los genéricos no se mezclan realmente.
Dan Dyer
3
La advertencia no verificada se puede eliminar si usa Arrays.copyOf (). Vea mi respuesta para una implementación.
Joachim Sauer el
@SuppressWarnings ("sin marcar")
Mark Renouf
13

Si lo usa de esta manera, no necesita importar ninguna clase de terceros.

Si quieres concatenar String

Código de muestra para concatenar dos String Array

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

Si quieres concatenar Int

Código de muestra para concatar dos matrices enteras

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

Aquí está el método principal

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

        }
    }  

Podemos usar de esta manera también.

Raj S. Rusia
fuente
11

Perdóname por agregar otra versión a esta lista ya larga. Miré cada respuesta y decidí que realmente quería una versión con solo un parámetro en la firma. También agregué algunas comprobaciones de argumentos para beneficiarse de una falla temprana con información sensible en caso de entrada inesperada.

@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;
}
Zalumon
fuente
Resumiría la longitud en el mismo ciclo en el que está haciendo su verificación nula, pero este es un muy buen resumen de las otras respuestas aquí. Creo que incluso maneja tipos intrínsecos como "int" sin cambiarlos a objetos Integer, que es realmente la ÚNICA razón para tratarlos como matrices en lugar de simplemente cambiar todo a ArrayLists. Además, su método podría tomar 2 matrices y un parámetro (...) para que la persona que llama sepa que necesita pasar al menos dos matrices antes de ejecutarlo y vea el error, pero eso complica el código de bucle ...
Bill K
11

Puede intentar convertirlo en una Arraylist y usar el método addAll y luego volver a convertirlo en una matriz.

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();
Pablo
fuente
Buena solución: sería mejor si el código se refactorizara para evitar matrices por completo a favor de ArrayLists, pero eso está fuera del control de la "Respuesta" y depende del interrogador.
Bill K
Cuento que requiere 4 objetos temporales adicionales para funcionar.
rghome
@rghome, al menos no requiere una biblioteca adicional para implementar una tarea tan simple
Farid
9

Usando flujos Java 8+ puedes escribir la siguiente función:

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

Aquí una posible implementación en el código de trabajo de la solución de pseudocódigo escrita por silvertab.

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

El siguiente es la interfaz del generador.

Nota: Un generador es necesario porque en Java no es posible hacer

new T[size]

debido a la eliminación de tipo genérico:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

Aquí un constructor concreto implementando la interfaz, construyendo una Integermatriz:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

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

Y finalmente la aplicación / prueba:

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

Esto debería ser de una sola línea.

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

¡Guauu! Aquí hay muchas respuestas complejas, incluidas algunas simples que dependen de dependencias externas. ¿Qué tal hacerlo así:

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]);
Doles
fuente
1
.. Pero ineficiente y lento.
JonasCz - Restablece a Mónica el
6

Esto funciona, pero debe insertar su propia comprobación de errores.

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

Probablemente no sea el más eficiente, pero no se basa en otra cosa que no sea la propia API de Java.

pegamento
fuente
2
+1. Sería mejor reemplazar el segundo forbucle con eso:for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
2010
Use String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)para omitir el primer forbucle. Ahorra tiempo proporcional al tamaño de arr1.
John Meyer
5

Esta es una función convertida para una matriz de cadenas:

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;
}
Oritm
fuente
5

¿Qué tal simplemente

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

Y solo hazlo Array.concat(arr1, arr2). Mientras arr1yarr2 sean del mismo tipo, esto le dará otra matriz del mismo tipo que contiene ambas matrices.

Efraín
fuente
Por razones de rendimiento, calcularía previamente el tamaño final de ArrayList porque ArrayList, por definición, asigna una nueva matriz y copia sus elementos cada vez que la matriz actual está llena. De lo contrario, iría directamente a LinkedList que no sufre ese problema
usr-local-ΕΨΗΕΛΩΝ
5

Una versión estática genérica que utiliza System.arraycopy de alto rendimiento sin requerir una anotación @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;
}
Beaudet
fuente
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;
}
Sujay
fuente
4

Aquí está mi versión ligeramente mejorada del concatAll de Joachim Sauer. Puede funcionar en Java 5 o 6, utilizando System.arraycopy de Java 6 si está disponible en tiempo de ejecución. Este método (en mi humilde opinión) es perfecto para Android, ya que funciona en Android <9 (que no tiene System.arraycopy) pero utilizará el método más rápido si es posible.

  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;
  }
candrews
fuente
1
Buena idea general, pero para cualquier persona que implemente: prefiero una versión con copia y otra sin copia que una que haga ambas cosas a modo de reflexión.
rektide
4

Otra forma de pensar sobre la pregunta. Para concatenar dos o más matrices, uno debe hacer una lista de todos los elementos de cada matriz y luego construir una nueva matriz. Esto suena como crear un List<T>y luego lo invoca toArray. Algunas otras respuestas usan ArrayList, y eso está bien. Pero, ¿qué tal si implementamos el nuestro? No es dificil:

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

Creo que lo anterior es equivalente a las soluciones que utiliza System.arraycopy. Sin embargo, creo que este tiene su propia belleza.

Motor de tierra
fuente
4

Qué tal si :

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()]);
}
clément francomme
fuente
4

Una variación simple que permite la unión de más de una matriz:

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()]);
}
Damo
fuente
3

Usando solo la propia API de 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]);
}

Ahora, este código no es el más eficiente, pero se basa solo en clases estándar de Java y es fácil de entender. Funciona para cualquier número de String [] (incluso cero arrays).

kiwi
fuente
15
Tuve que rechazar este para toda la creación innecesaria de objetos List.
Outlaw Programmer