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

1366

J'ai besoin de concaténer deux Stringtableaux en Java.

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

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

Antti Kissaniemi
la source
3
Bytes.concat de Guava
Ben Page
1
Je vois beaucoup de réponses ici mais la question est tellement libellée ('façon la plus simple'?) Qu'elle ne permet pas d'indiquer la meilleure réponse ...
Artur Opalinski
2
Des dizaines de réponses ici copient les données dans un nouveau tableau car c'est ce qui a été demandé - mais copier des données lorsqu'elles ne sont pas strictement nécessaires est une mauvaise chose à faire, surtout en Java. À la place, gardez une trace des index et utilisez les deux tableaux comme s'ils étaient joints. J'ai ajouté une solution illustrant la technique.
Douglas tenue le
12
Le fait qu'une question comme celle-ci ait actuellement 50 réponses différentes me fait me demander pourquoi Java n'a jamais obtenu une simple array1 + array2concaténation.
JollyJoker
2
Vous pouvez le faire parfaitement bien et très efficacement dans deux lignes de Java standard (voir ma réponse), donc il n'y a pas énormément à gagner en ayant une seule méthode pour le faire. Toutes ces solutions étranges et merveilleuses sont un peu une perte de temps.
rghome

Réponses:

1093

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

Code:

String[] both = ArrayUtils.addAll(first, second);
Antti Kissaniemi
la source
175
Comment est-ce "tricher" s'il répond à la question? Bien sûr, avoir une dépendance supplémentaire est probablement exagéré pour cette situation spécifique, mais aucun mal n'est fait en appelant qu'elle existe, d'autant plus qu'il y a tellement d'excellents éléments de fonctionnalité dans Apache Commons.
Rob
33
Je suis d'accord, cela ne répond pas vraiment à la question. Les bibliothèques de haut niveau peuvent être excellentes, mais si vous voulez apprendre un moyen efficace de le faire, vous voulez regarder le code que la méthode de bibliothèque utilise. De plus, dans de nombreuses situations, vous ne pouvez pas simplement parcourir une autre bibliothèque du produit à la volée.
AdamC
76
Je pense que c'est une bonne réponse. Des solutions POJO ont également été fournies, mais si l'OP utilise déjà Apache Commons dans son programme (tout à fait possible compte tenu de sa popularité), il ne connaît peut-être pas encore cette solution. Ensuite, il ne serait pas en "ajoutant une dépendance pour cette méthode", mais ferait un meilleur usage d'une bibliothèque existante.
Adam
14
Si vous êtes toujours inquiet de ne pas ajouter de bibliothèque pour une seule méthode, aucune nouvelle bibliothèque ne sera ajoutée. Étant donné les excellents utilitaires présents dans Apache Commons, je recommande fortement de l'ajouter lors du tout premier cas d'utilisation.
Hindol
6
l'utilisation d'apache commons ne devrait jamais être appelée «tricherie». Je doute de la raison des développeurs qui pensent que c'est une dépendance inutile.
Jeryl Cook
768

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

Notez qu'il ne fonctionnera pas avec les types de données primitifs, uniquement avec les types d'objets.

La version suivante, légèrement plus compliquée, fonctionne avec les tableaux d'objets et les tableaux primitifs. Il le fait en utilisant Tau 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 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 }));
Lii
la source
1
J'aime cette suggestion car elle dépend moins des dernières versions de Java. Dans mes projets, je suis souvent bloqué en utilisant des versions plus anciennes de profils Java ou CLDC où certaines des fonctionnalités comme celles mentionnées par Antti ne sont pas disponibles.
kvn
4
La ligne suivante cassera la partie générique: concaténer (nouvelle chaîne [] {"1"}, nouvel objet [] {nouvel objet ()})
dragon66
ce serait bien de ne pas avoir à utiliser l'annotation @SuppressWarnings - je posterai une solution pour cela ci-dessous.
beaudet
+1 pour Array.newInstance(a.getClass().getComponentType(), aLen + bLen);. Je n'ai étonnamment jamais vu ça auparavant. @beaudet Je pense que l'annotation est très bien ici, vu pourquoi elle est supprimée.
Blake
1
ha, appelez-moi un puriste mais je préfère un code propre qui ne nécessite pas la suppression des avertissements pour supprimer les avertissements
beaudet
475

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 elles utilisentArrays.copyOf()

Les deux versions évitent de créer des Listobjets intermédiaires et les utilisent System.arraycopy()pour garantir 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), cela 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;
}
Joachim Sauer
la source
10
@djBO: pour les tableaux de type primitif, vous devez effectuer une surcharge pour chaque type: copiez simplement le code et remplacez-les Tpar byte(et perdez le <T>).
Joachim Sauer
pouvez-vous me dire comment utiliser le type d'opérateur <T> dans ma classe?
Johnydep
6
J'ajouterais cela au début, juste pour être défensif. if (first == null) {if (second == null) {return null; } retourne en second; } if (second == null) {return first; }
marathon
4
@djBo: qu'en est-il de:ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
Sam Goldberg
18
Il y a un bogue dans cette approche qui devient apparent si vous appelez ces fonctions avec des tableaux de différents types de composants, par exemple concat(ai, ad), où aiest Integer[]et adest Double[]. (Dans ce cas, le paramètre type <T>est résolu <? extends Number>par le compilateur.) Le tableau créé par Arrays.copyOfaura le type de composant du premier tableau, c'est- Integerà- dire dans cet exemple. Lorsque la fonction est sur le point de copier le deuxième tableau, un ArrayStoreExceptionsera lancé. La solution est d'avoir un Class<T> typeparamètre supplémentaire .
T-Bull
457

Utilisation Streamen Java 8:

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

Ou comme ça, en utilisant flatMap:

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

Pour ce faire, pour un type générique, vous devez utiliser la réflexion:

@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
    size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));
Lii
la source
28
Est-ce efficace?
Supuhstar
8
A lire: jaxenter.com/… tl; dr - les streams peuvent être performants ou non, cela dépend de ce que vous en faites et des contraintes du problème (n'est-ce pas toujours la réponse? Lol)
Trevor Brown
6
De plus, si a ou b sont des tableaux de types primitifs, leurs flux devront l'être .boxed()afin qu'ils soient de type Streamplutôt que par exemple IntStreamqui ne peuvent pas être passés en paramètre à Stream.concat.
Will Hardwick-Smith
17
@Will Hardwick-Smith: non, vous n'avez qu'à choisir la bonne classe de flux, par exemple si aet bêtes int[], utilisezint[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
Holger
3
@Supuhstar: Ce n'est probablement pas aussi rapide que System.arrayCopy. Mais pas particulièrement lent non plus. Vous devrez probablement le faire très souvent avec des tableaux énormes dans des contextes très sensibles aux performances pour que la différence de temps d'exécution soit importante.
Lii
191

Ou avec la bien-aimée Goyave :

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

Il existe également 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)
KARASZI István
la source
Autant que j'aime Guava, la méthode d'Apache Commons traite mieux les nullables.
Ravi Wallau
7
Bien qu'il soit bon d'utiliser des bibliothèques, il est regrettable que le problème ait été résolu. Par conséquent, la solution sous-jacente reste insaisissable.
user924272
51
Quel est le problème de l'abstraction? Je ne sais pas quel est le problème avec réinventer la roue ici, si vous voulez apprendre le problème, vérifiez la source ou lisez-le. Le code professionnel devrait utiliser des bibliothèques de haut niveau, bien mieux s'il est développé dans Google!
Breno Salgado
@RaviWallau Pourriez-vous créer un lien vers la classe qui fait cela?
Sébastien Tromp du
1
@ SébastienTromp C'est la meilleure solution pour cette question - ArrayUtils.
Ravi Wallau
70

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

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

Il s'agit d'une solution rapide et efficace qui fonctionnera pour les types primitifs ainsi que les deux méthodes impliquées sont surchargées.

Vous devez éviter les solutions impliquant des listes de tableaux, des flux, etc. car celles-ci devront allouer de la mémoire temporaire sans but utile.

Vous devez éviter les forboucles pour les grands tableaux car ceux-ci ne sont pas efficaces. Les méthodes intégrées utilisent des fonctions de copie de blocs extrêmement rapides.

rghome
la source
1
C'est l'une des meilleures solutions. Java 100% standard. Rapide / efficace. Devrait obtenir plus de votes positifs!
Shebla Tsama
58

Utilisation de 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()]);
}
Fabian Steeg
la source
13
Simplement, mais inefficace car il crée un tableau pour ArrayList puis en génère un autre pour la méthode toArray. Mais toujours valable car c'est simple à lire.
PhoneixS
1
applicable pour les chaînes et les objets (comme la question le veut), mais il n'y a pas de méthode addAll pour les types primaires (en pouces)
joro
Comme expliqué dans cet article , l'utilisation both.toArray(new String[0])sera plus rapide que both.toArray(new String[both.size()]), même si elle contredit notre intuition naïve. C'est pourquoi il est si important de mesurer les performances réelles lors de l'optimisation. Ou utilisez simplement la construction plus simple, lorsque l'avantage de la variante plus compliquée ne peut pas être prouvé.
Holger
42

Une solution 100% java ancienne et sans 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;
}
francois
la source
retravaillé le mien pour File [], mais c'est la même chose. Merci pour votre solution
ShadowFlame
5
Probablement assez inefficace.
JonasCz
Vous voudrez peut-être ajouter des nullchèques. Et peut-être définir certaines de vos variables final.
Tripp Kinetics du
Les nullvérifications @TrippKinetics masqueraient les NPE plutôt que de les afficher et l'utilisation de final pour les var locales n'a aucun avantage (pour l'instant).
Maarten Bodewes
1
@Maarten Bodewes Je pense que vous trouverez (si vous le comparez, ce que j'ai) que le for-each s'exécute en même temps que la boucle indexée sur les dernières versions de Java. L'optimiseur s'en charge.
rghome
33

J'ai récemment combattu des problèmes de rotation excessive de la mémoire. Si a et / ou b sont connus pour être généralement vides, voici une autre adaptation du code de silvertab (également généré):

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

Edit: Une version précédente de ce message a déclaré que la réutilisation de la baie comme celle-ci doit être clairement documentée. Comme le souligne Maarten dans les commentaires, il serait généralement préférable de simplement supprimer les instructions if, ce qui rendrait inutile la documentation. Mais là encore, ces déclarations if étaient le point entier de cette optimisation particulière en premier lieu. Je vais laisser cette réponse ici, mais méfiez-vous!

volley
la source
5
cela signifie cependant que vous renvoyez le même tableau et que la modification d'une valeur sur le tableau renvoyé modifie la valeur à la même position que le tableau d'entrée renvoyé.
Lorenzo Boccaccia
Oui - voir le commentaire à la fin de mon article concernant la réutilisation des baies. La surcharge de maintenance imposée par cette solution en valait la peine dans notre cas particulier, mais la copie défensive devrait probablement être utilisée dans la plupart des cas.
volley
Lorenzo / volley, pouvez-vous expliquer quelle partie du code provoque la réutilisation des tableaux? Je pensais que System.arraycopyle contenu du tableau était copié?
Rosdi Kasim
4
Un appelant s'attendrait normalement à ce qu'un appel à concat () renvoie un tableau nouvellement alloué. Si a ou b est nul, concat () renverra cependant l'un des tableaux passés dans celui-ci. Cette réutilisation est ce qui peut être inattendu. (Oui, la copie sur tableau ne fait que la copie. La réutilisation vient du retour de a ou b directement.)
volley
Le code doit être aussi explicite que possible. Les personnes qui lisent le code ne devraient pas avoir à rechercher le JavaDoc d'une fonction appelée pour découvrir qu'elle fait une chose pour une condition particulière et quelque chose d'autre pour une autre. En bref: vous ne pouvez généralement pas résoudre des problèmes de conception comme ceux-ci avec un commentaire. Le ifsimple fait de laisser de côté les deux déclarations serait la solution la plus simple.
Maarten Bodewes
27

La bibliothèque Java fonctionnelle possède une classe d'encapsuleur de tableaux qui équipe les tableaux de méthodes pratiques comme la concaténation.

import static fj.data.Array.array;

...et alors

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

Pour récupérer le tableau déballé, appelez

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

both.toArray(new String[0]);
nick-s
la source
3
La réponse est excellente mais un tout petit peu cassée. Pour le rendre parfait, vous devez passer à toArray () un tableau du type dont vous avez besoin. Dans l'exemple ci-dessus, le code doit être: both.toArray (new String [0]) Voir: stackoverflow.com/questions/4042434/…
Ronen Rabinovici
Je ne sais pas pourquoi cette réponse n'est pas mieux notée ... bien qu'elle semble avoir besoin du changement suggéré par @RonenRabinovici
drmrbrewer
4
Ou mieux, sans allocation inutile de tableau de longueur nulle both.toArray(new String[both.size()])
:;
1
@Honza lecture recommandée
Holger
Salut @Honza, possible de faire de même pour retourner un tableau entier primitif en 3 lignes?
jumping_monkey
18

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); 
  }
Vaseph
la source
17

Voici une adaptation de la solution de silvertab, avec des génériques modernisés:

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

REMARQUE: voir la réponse de Joachim pour une solution Java 6. Non seulement cela élimine l'avertissement; il est également plus court, plus efficace et plus facile à lire!

volley
la source
Vous pouvez supprimer l'avertissement pour cette méthode, mais à part cela, vous ne pouvez pas faire grand-chose. Les tableaux et les génériques ne se mélangent pas vraiment.
Dan Dyer
3
L'avertissement non contrôlé peut être éliminé si vous utilisez Arrays.copyOf (). Voir ma réponse pour une implémentation.
Joachim Sauer le
@SuppressWarnings ("non contrôlé")
Mark Renouf
13

Si vous utilisez cette méthode, vous n'avez donc pas besoin d'importer de classe tierce.

Si vous voulez concaténer String

Exemple de code pour concéder deux tableaux de chaînes

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éner Int

Exemple de code pour concéder deux tableaux 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 également utiliser cette méthode.

Raj S. Rusia
la source
11

Veuillez me pardonner d'avoir ajouté 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é quelques vérifications d'arguments pour bénéficier d'un échec précoce avec des informations sensibles 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;
}
Zalumon
la source
Je résumerais la longueur dans la même boucle où vous faites votre vérification nulle - mais c'est un très bon résumé des autres réponses ici. Je crois qu'il gère même les types intrinsèques comme "int" sans les changer en objets Integer, ce qui est vraiment la SEULE raison de les traiter comme des tableaux plutôt que de simplement tout changer en ArrayLists. De plus, votre méthode pourrait prendre 2 tableaux et un paramètre (...) pour que l'appelant sache qu'il doit passer au moins deux tableaux avant de l'exécuter et de voir l'erreur, mais cela complique le code de boucle ....
Bill K
11

Vous pouvez essayer de le convertir en Arraylist et utiliser la méthode addAll puis reconvertir en tableau.

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();
Paul
la source
Bonne solution - serait mieux si le code était refactorisé pour éviter complètement les tableaux en faveur de ArrayLists, mais cela échappe au contrôle de la «réponse» et au questionneur.
Bill K
Je compte qu'il faut 4 objets temporaires supplémentaires pour fonctionner.
rghome
@rghome, au moins il ne nécessite pas de bibliothèque supplémentaire pour implémenter une tâche aussi simple
Farid
9

En utilisant les flux Java 8+, vous pouvez écrire la fonction suivante:

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

Voici une implémentation possible en code de travail de la solution de 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;
   }
}

Voici ensuite l'interface du générateur.

Remarque: Un constructeur est nécessaire car en java il n'est pas possible de faire

new T[size]

en raison de l'effacement de type générique:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

Voici un constructeur concret implémentant l'interface, construisant un Integertableau:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

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

Et enfin l'application / 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]);
   }
}
hpgisler
la source
7

Cela devrait être une ligne.

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

Hou la la! beaucoup de réponses complexes ici, y compris des réponses simples qui dépendent de dépendances externes. que diriez-vous de faire comme ça:

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
la source
1
..Mais inefficace et lent.
JonasCz
6

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 repose sur rien d'autre que la propre API de Java.

colle
la source
2
+1. Il serait préférable de remplacer la deuxième forboucle par celle-ci:for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
danseur
Utilisez String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)pour sauter la première forboucle. Gain de temps proportionnel à la taille de arr1.
John Meyer
5

Il s'agit d'une fonction convertie pour un tableau 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;
}
Oritm
la source
5

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 fais-le Array.concat(arr1, arr2). Tant que arr1et arr2sont du même type, cela vous donnera un autre tableau du même type contenant les deux tableaux.

Ephraim
la source
Pour des raisons de performances, je pré-calculerais la taille finale de la ArrayList car ArrayList, par définition, alloue un nouveau tableau et copie ses éléments chaque fois que le tableau actuel est plein. Sinon, j'irais directement pour LinkedList qui ne souffre pas d'un tel problème
usr-local-ΕΨΗΕΛΩΝ
5

Une version statique générique qui utilise le System.arraycopy très performant sans nécessiter une annotation @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
la source
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
la source
4

Voici ma version légèrement améliorée de concatAll de Joachim Sauer. Il peut fonctionner sur Java 5 ou 6, en utilisant System.arraycopy de Java 6 s'il est disponible au moment de l'exécution. Cette méthode (à mon humble avis) est parfaite pour Android, car elle fonctionne sur Android <9 (qui n'a pas System.arraycopy) mais utilisera la méthode la 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;
  }
candrews
la source
1
Bonne idée générale, mais pour quiconque l'implémente: je préférerais une version copyOf et non-copyOf plutôt qu'une version qui fait les deux à titre de réflexion.
rektide
4

Une autre façon de penser la question. Pour concaténer deux tableaux ou plus, il suffit de répertorier tous les éléments de chaque tableau, puis de créer un nouveau tableau. Cela ressemble à créer un List<T>, puis l'appelle toArray. Certaines autres réponses sont utiles ArrayList, et c'est très bien. Mais que diriez-vous de mettre en œuvre le nôtre? Ce 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 aux solutions qui utilisent System.arraycopy. Cependant, je pense que celui-ci a sa propre beauté.

Earth Engine
la source
4

Que diriez-vous :

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
la source
4

Une variante simple permettant la jonction de plus d'un tableau:

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
la source
3

Utiliser uniquement la propre 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]);
}

Maintenant, ce code n'est pas le plus efficace, mais il ne repose que sur les classes java standard et est facile à comprendre. Cela fonctionne pour n'importe quel nombre de String [] (même zéro tableau).

kiwi
la source
15
J'ai dû déprécier celui-ci pour toute la création inutile d'objets List.
Programmeur hors