Frage Wie kann ich zwei Arrays in Java verketten?


Ich muss zwei String-Arrays in Java verketten.

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

Was ist der einfachste Weg, dies zu tun?


1134


Ursprung


Antworten:


Ich habe eine One-Line-Lösung aus der guten alten Apache Commons Lang-Bibliothek gefunden.
  ArrayUtils.addAll(T[], T...)

Code:

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

922



Hier ist eine einfache Methode, die zwei Arrays verketten und das Ergebnis zurückgeben wird:

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

Beachten Sie, dass es nicht mit Primitiven funktioniert, sondern nur mit Objekttypen.

Die folgende etwas kompliziertere Version funktioniert sowohl mit Objekt- als auch mit Primitivarrays. Es tut dies, indem es benutzt T Anstatt von T[] als Argumenttyp

Es ermöglicht auch die Verkettung von Arrays zweier verschiedener Typen, indem der allgemeinste Typ als Komponententyp des Ergebnisses ausgewählt wird.

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

Hier ist ein Beispiel:

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



Es ist möglich, eine vollständig generische Version zu schreiben, die sogar erweitert werden kann, um eine beliebige Anzahl von Arrays zu verketten. Diese Versionen benötigen Java 6, wie sie verwenden Arrays.copyOf()

Beide Versionen vermeiden die Erstellung eines Vermittlers List Objekte und verwenden System.arraycopy() um sicherzustellen, dass das Kopieren großer Arrays so schnell wie möglich ist.

Für zwei Arrays sieht das so aus:

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

Und für eine beliebige Anzahl von Arrays (> = 1) sieht das so aus:

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



Einzeiler in Java 8:

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

Oder:

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

326



Oder mit der Geliebten Guave:

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

Außerdem gibt es Versionen für primitive Arrays:

  • 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



Verwenden der Java-API:

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



Eine Lösung 100% altes Java und ohne  System.arraycopy (z. B. nicht im GWT-Client verfügbar):

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



Ich habe kürzlich Probleme mit übermäßiger Speicherrotation bekämpft. Wenn a und / oder b bekanntermaßen häufig leer sind, folgt hier eine weitere Anpassung des Silvertab-Codes (auch generifiziert):

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

(In beiden Fällen muss das Array-Wiederverwendungsverhalten eindeutig JavaDeced sein!)


29



Das Funktionales Java Bibliothek hat eine Array-Wrapper-Klasse, die Arrays mit praktischen Methoden wie Verkettung ausstattet.

import static fj.data.Array.array;

...und dann

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

Um das ausgepackte Array wieder zu entfernen, rufen Sie an

String[] s = both.array();

26



ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));

both.toArray(new String[0]);

22



Hier ist eine Anpassung der Silvertab-Lösung, mit Generika nachgerüstet:

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

HINWEIS: Siehe Joachim's Antwort für eine Java 6 Lösung. Es beseitigt nicht nur die Warnung; es ist auch kürzer, effizienter und einfacher zu lesen!


17