Question Comment puis-je concaténer deux tableaux en Java?


J'ai besoin de concaténer deux tableaux de chaînes en Java.

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

Quelle est la manière la plus simple de faire ça?


1134


origine


Réponses:


J'ai trouvé une solution d'une ligne de la bonne vieille bibliothèque Apache Commons Lang.
  ArrayUtils.addAll(T[], T...)

Code:

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

922



Voici une méthode simple qui va concaténer deux tableaux et retourner 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;
}

Notez que cela ne fonctionnera pas avec les primitives, seulement avec les types d'objets.

La version légèrement plus compliquée suivante fonctionne avec les tableaux d'objets et de primitives. Il le fait en utilisant T au lieu de T[] comme type d'argument.

Il permet également de concaténer des tableaux de deux types différents en choisissant le type le plus général en tant que 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 }));

721



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. Ces versions nécessitent Java 6, car ils utilisent Arrays.copyOf()

Les deux versions évitent de créer un intermédiaire List objets et utilisation System.arraycopy() pour s'assurer que la copie de grands tableaux est aussi rapide que possible.

Pour deux tableaux, cela 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 un 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;
}

440



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

326



Ou avec le bien-aimé Goyave:

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

En outre, il existe 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)

168



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

53



Une solution 100% vieux java et sans pour autant  System.arraycopy (non disponible dans le client GWT 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;
}

36



J'ai récemment combattu des problèmes avec une rotation excessive de la mémoire. Si on sait que a et / ou b sont généralement vides, voici une autre adaptation du code de silvertab (générée 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 JavaDoced!)


29



le Java fonctionnel library a une classe wrapper array qui équipe les tableaux avec des méthodes pratiques comme la concaténation.

import static fj.data.Array.array;

...et alors

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

Pour sortir le tableau déballé, appelez

String[] s = both.array();

26