Comment concaténer deux tableaux en Java?

je dois concaténer deux tableaux de chaîne en Java.

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

Quelle est la meilleure façon de le faire?

1151
demandé sur Antti Sykäri 2008-09-17 10:14:23

30 réponses

j'ai trouvé une solution à une ligne de la bonne vieille bibliothèque Lang Apache Commons.

ArrayUtils.addAll(T[], T...)

Code:

String[] both = (String[])ArrayUtils.addAll(first, second);
932
répondu Antti Sykäri 2015-12-19 00:06:13

Voici une méthode simple qui concaténera deux tableaux et retournera le résultat:

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

Note Comme si cela ne fonctionnait pas avec les primitives, seulement avec les types d'objets.

la version suivante un peu plus compliquée fonctionne à la fois avec des tableaux objet et primitifs. Il le fait en utilisant T au lieu de T[] comme type d'argument.

il permet également de concaténer des matrices de deux différents types En choisissant le type le plus général comme type de composant du résultat.

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

voici un exemple:

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 }));
725
répondu Lii 2017-12-23 15:39:26

il est possible d'écrire une version entièrement générique qui peut même être étendue pour concaténer n'importe quel nombre de tableaux. Cette version nécessite Java 6, car ils utilisent Arrays.copyOf()

les deux versions évitent de créer des objets intermédiaires List et utilisent System.arraycopy() pour s'assurer que la copie de grands tableaux est aussi rapide que possible.

pour deux tableaux il ressemble à ceci:

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

et pour nombre arbitraire de tableaux (>= 1), il ressemble à ceci:

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;
}
442
répondu Joachim Sauer 2009-04-24 07:28:01

One-liner en Java 8:

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

ou:

String[] both = Stream.of(a, b).flatMap(Stream::of)
                      .toArray(String[]::new);
341
répondu Vitalii Fedorenko 2015-05-13 10:00:11

ou avec le bien-aimé Goyave :

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

il existe aussi des versions pour les tableaux primitifs:

  • 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)
169
répondu KARASZI István 2017-03-27 09:55:29

utilisant 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()]);
}
54
répondu Fabian Steeg 2012-04-21 16:34:49
"151920920 Une" solution 100% old java et sans System.arraycopy (non disponible dans GWT client par exemple):

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;
}
37
répondu francois 2016-02-26 08:06:25

j'ai récemment combattu des problèmes de rotation excessive de la mémoire. Si l'on sait que a et/ou b sont généralement vides, voici une autre adaptation du code de silvertab (générifié aussi):

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

(dans les deux cas, le comportement de réutilisation du tableau doit être clairement Javadocisé!)

30
répondu volley 2008-09-25 16:24:07

la bibliothèque Java fonctionnel a une classe d'enrubannage de tableau qui fournit des tableaux avec des méthodes pratiques comme la concaténation.

import static fj.data.Array.array;

...et puis

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

pour obtenir le tableau non emballé de retour, appelez

String[] s = both.array();
26
répondu Apocalisp 2009-07-15 13:25:17
ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));

both.toArray(new String[0]);
25
répondu nick-s 2017-12-21 03:37:14

Vous pouvez ajouter les deux tableaux en deux lignes de code.

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

C'est une solution rapide et efficace et de travail pour les types primitifs, ainsi que les deux méthodes sont surchargées.

vous devez éviter les solutions impliquant des ArrayLists, des flux, etc car ceux-ci auront besoin d'allouer la mémoire temporaire sans but utile.

vous devez éviter les boucles for car elles ne sont pas efficaces. Construit dans le les méthodes utilisent des fonctions de copie de bloc qui sont extrêmement rapides.

20
répondu rghome 2018-04-16 17:59:40

voici une adaptation de la solution de silvertab, avec generics Retrofited:

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

NOTE: voir réponse de Joachim pour une solution Java 6. Non seulement il élimine l'avertissement, mais il est aussi plus court, plus efficace et plus facile à lire!

17
répondu volley 2017-05-23 12:02:57

une autre façon avec Java8 en utilisant 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); 
  }
16
répondu Vaseph 2016-02-10 12:48:08

si vous utilisez cette façon de sorte que vous n'avez pas besoin d'importer une classe de tiers.

si vous voulez concaténate String

Exemple de code pour concate deux Tableau de Chaîne

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 vous voulez concaténate Int

Exemple de code pour concate deux Tableau d'Entiers

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

Voici la méthode 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));

        }
    }  

nous pouvons utiliser cette façon aussi.

12
répondu Raj S. Rusia 2017-02-13 10:17:06

s'il vous plaît pardonnez-moi d'ajouter une autre version à cette liste déjà longue. J'ai regardé chaque réponse et j'ai décidé que je voulais vraiment une version avec un seul paramètre dans la signature. J'ai également ajouté une vérification des arguments pour bénéficier de l'échec précoce avec des informations sensées en cas d'entrée inattendue.

@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;
}
11
répondu Zalumon 2015-09-11 14:02:10

vous pouvez essayer de le convertir en un Arraylist et utiliser la méthode addAll puis convertir de nouveau en un tableau.

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();
10
répondu Paul 2015-11-14 18:45:36

ici une implémentation possible en code de travail de la solution pseudo code écrite par silvertab.

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

suit ensuite l'interface builder.

Note: un builder est nécessaire car en java il n'est pas possible de faire

new T[size]

dû au type générique erasure:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

voici un béton constructeur mettant en œuvre l'interface, la construction d'un Integer tableau:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

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

et enfin l'application / essai:

@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
répondu hpgisler 2012-01-04 14:35:54

Wow! beaucoup de réponses complexes ici, y compris quelques réponses simples qui dépendent de dépendances externes. Que diriez-vous de le faire comme ceci:

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]);
6
répondu doles 2012-10-28 20:23:12

il s'agit d'une fonction convertie pour un tableau de chaînes de caractères:

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
répondu Oritm 2011-06-11 19:59:56

Que Diriez-vous simplement

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

Et il suffit de faire Array.concat(arr1, arr2) . Tant que arr1 et arr2 sont du même type, cela vous donnera un autre tableau du même type contenant les deux tableaux.

5
répondu Ephraim 2015-05-10 19:30:16

Cela fonctionne, mais vous devez insérer votre propre vérification d'erreur.

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

Ce n'est probablement pas le plus efficace, mais il ne s'appuie sur rien d'autre que la propre API Java.

5
répondu glue 2015-05-10 19:42:25

voici ma version légèrement améliorée du concatAll de Joachim Sauer. Il peut fonctionner sur Java 5 ou 6, en utilisant le système de Java 6.arraycopy si elle est disponible à l'exécution. Cette méthode (IMHO) est parfaite pour Android, car il fonctionne sur Android <9 (qui n'a pas de système.arraycopy) mais utilisera la méthode plus rapide si possible.

  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;
  }
4
répondu candrews 2011-06-09 15:48:05

une autre façon de penser à la question. Pour concaténer deux ou plusieurs tableaux, il faut faire la liste de tous les éléments de chaque tableau, puis construire un nouveau tableau. Cela ressemble à créer un List<T> et appelle ensuite toArray . D'autres réponses utilisent ArrayList , et c'est très bien. Mais comment mettre en œuvre notre propre? Il n'est pas 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);
}

je crois que ce qui précède est équivalent à des solutions qui utilisent System.arraycopy . Cependant, je pense que ce qu'on a sa propre beauté.

4
répondu Earth Engine 2013-02-27 03:03:56

Que Diriez-vous de:

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
répondu clément francomme 2015-02-11 23:35:38

variation simple permettant l'assemblage de plusieurs réseaux:

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()]);
}
4
répondu Damo 2015-05-10 19:38:45

utilisant uniquement L'API Javas own:


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

maintenant, ce code n'est pas le plus efficace, mais il s'appuie uniquement sur les classes java standard et est facile à comprendre. Il fonctionne pour n'importe quel nombre de chaîne[] (même zéro tableaux).

3
répondu Kiwi 2008-09-17 08:02:41

une façon facile, mais inefficace, de le faire (génériques non inclus):

ArrayList baseArray = new ArrayList(Arrays.asList(array1));
baseArray.addAll(Arrays.asList(array2));
String concatenated[] = (String []) baseArray.toArray(new String[baseArray.size()]);
3
répondu MetroidFan2002 2009-06-18 14:08:24
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;
}
3
répondu Sujay 2010-12-29 07:29:11
String [] both = new ArrayList<String>(){{addAll(Arrays.asList(first)); addAll(Arrays.asList(second));}}.toArray(new String[0]);
3
répondu Frimousse 2013-06-21 12:59:12

Un type indépendant de la variation (mis à JOUR grâce à la Volée pour l'instanciation T):

@SuppressWarnings("unchecked")
public static <T> T[] join(T[]...arrays) {

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

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

    return output.toArray((T[])Array.newInstance(
        arrays[0].getClass().getComponentType(), output.size()));
}
3
répondu Damo 2015-05-10 19:38:07