¿Cómo puedo concatenar dos matrices en Java?

Necesito concatenar dos matrices de cadenas en Java.

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

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

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

Código:

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

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

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

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

La siguiente versión ligeramente más complicada funciona tanto con matrices primitivas como con objetos. Hace esto usando T lugar 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 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 })); 

Es posible escribir una versión completamente genérica que incluso se puede extender para concatenar cualquier cantidad de matrices. Estas versiones requieren Java 6, ya que usan Arrays.copyOf()

Ambas versiones evitan la creación de objetos List intermedios y usan System.arraycopy() para garantizar que la copia de matrices grandes sea lo más rápida posible.

Para dos matrices, se ve así:

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

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

 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 en 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 la amada Guava :

 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)

Usando la API de 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 solución 100% vieja de Java y sin 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; } 

Recientemente luché contra problemas con la rotación excesiva de memoria. Si se sabe que a y / o b están comúnmente vacíos, aquí hay otra adaptación del código de silvertab (también generizado):

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

(En cualquier caso, ¡el comportamiento de reutilización de la matriz debe ser claramente JavaDoced!)

La biblioteca funcional de Java tiene una clase de envoltura de matriz que equipa las matrices con métodos prácticos como la concatenación.

 import static fj.data.Array.array; 

…y entonces

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

Para volver a sacar la matriz desenvuelta, llame

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

Aquí hay una adaptación de la solución de Silvertab, con generics adaptados:

 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: 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!

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

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 que funcionará para los tipos primitivos y los dos métodos involucrados están sobrecargados.

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

Debe evitar los bucles ya que estos no son eficientes. Los métodos integrados utilizan funciones de copia en bloque que son extremadamente rápidas.

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

Si quieres concatenar String

Código de muestra para concatenar dos matrices de cadenas

 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 concatenar dos matrices de enteros

 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.

Por favor, perdónenme por agregar otra versión a esta larga lista. Miré cada respuesta y decidí que realmente quería una versión con solo un parámetro en la firma. También agregué algunos argumentos para sacar provecho de una falla temprana con información sensible en caso de una entrada inesperada.

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

Podría tratar de convertirlo en un 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(); 

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

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

A continuación está la interfaz del constructor.

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

new T[size]

debido al borrado de tipo genérico:

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

Aquí un constructor concreto que implementa la interfaz, construyendo una matriz Integer :

 public class IntegerArrayBuilder implements ArrayBuilderI { @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]); } } 

¡Guauu! muchas respuestas complejas aquí, incluidas algunas simples que dependen de dependencias externas. ¿Qué tal si lo haces así?

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

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

¿Qué tal simplemente?

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

Y simplemente haz Array.concat(arr1, arr2) . Siempre que arr1 y arr2 sean del mismo tipo, esto le dará otra matriz del mismo tipo que contenga ambas matrices.

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 depende de otra API que no sea Java.

Aquí está mi versión ligeramente mejorada de 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 usará el método más rápido si es posible.

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

Otra forma de pensar sobre la pregunta. Para concatenar dos o más matrices, uno tiene que hacer es enumerar todos los elementos de cada arrays, y luego construir una nueva matriz. Esto suena como crear una List y luego llama a toArray en ella. Algunas otras respuestas usan ArrayList , y eso está bien. Pero ¿qué hay de implementar nuestro propio? No es dificil:

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

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

Qué tal si :

 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 variación simple que permite la unión de más de una matriz:

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

Usando solo 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 bien, 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 cantidad de String [] (incluso matrices de cero).

Una manera fácil, pero ineficiente, de hacer esto (generics no incluidos):

 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 variación independiente del tipo (ACTUALIZADO, gracias a Volley por crear instancias de 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())); } 
Intereting Posts