Bagaimana saya bisa menggabungkan dua array di Jawa?

1366

Saya perlu menggabungkan dua Stringarray di Jawa.

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

Apa cara termudah untuk melakukan ini?

Antti Kissaniemi
sumber
3
Bytes.concat dari Guava
Ben Page
1
Saya melihat banyak tanggapan di sini tetapi pertanyaannya sangat jelas ('cara termudah'?) Sehingga tidak memungkinkan untuk menunjukkan jawaban terbaik ...
Artur Opalinski
2
Puluhan jawaban di sini menyalin data ke array baru karena itulah yang diminta - tetapi menyalin data ketika tidak benar-benar diperlukan adalah hal yang buruk untuk dilakukan terutama di Jawa. Alih-alih, pantau indeks dan gunakan dua array seolah-olah bergabung. Saya telah menambahkan solusi yang menggambarkan teknik ini.
Douglas Diadakan
12
Fakta bahwa pertanyaan seperti ini saat ini memiliki 50 jawaban berbeda membuat saya bertanya-tanya mengapa Jawa tidak pernah mendapatkan array1 + array2rangkaian sederhana .
JollyJoker
2
Anda dapat melakukannya dengan sangat baik dan sangat efisien dalam dua baris Java standar (lihat jawaban saya), sehingga tidak ada banyak hal buruk yang dapat diperoleh dengan memiliki satu metode untuk melakukannya. Semua solusi aneh dan luar biasa ini hanya buang-buang waktu saja.
rghome

Jawaban:

1093

Saya menemukan solusi satu baris dari perpustakaan lama Apache Commons Lang yang bagus.
ArrayUtils.addAll(T[], T...)

Kode:

String[] both = ArrayUtils.addAll(first, second);
Antti Kissaniemi
sumber
175
Bagaimana "curang" jika menjawab pertanyaan? Tentu, memiliki ketergantungan ekstra mungkin berlebihan untuk situasi khusus ini, tetapi tidak ada salahnya memanggil bahwa itu ada, terutama karena ada begitu banyak bit fungsionalitas yang sangat baik di Apache Commons.
Rob
33
Saya setuju, ini tidak benar-benar menjawab pertanyaan. Pustaka tingkat tinggi bisa bagus, tetapi jika Anda ingin mempelajari cara yang efisien untuk melakukannya, Anda ingin melihat kode yang digunakan metode perpustakaan. Juga, dalam banyak situasi, Anda tidak bisa hanya melalui perpustakaan lain di produk dengan cepat.
AdamC
76
Saya pikir ini adalah jawaban yang bagus. Solusi POJO juga telah disediakan, tetapi jika OP sudah menggunakan Apache Commons dalam program mereka (semuanya mungkin mempertimbangkan popularitasnya) ia mungkin masih belum tahu solusi ini. Maka dia tidak akan "menambahkan ketergantungan untuk metode yang satu ini," tetapi akan memanfaatkan perpustakaan yang ada dengan lebih baik.
Adam
14
Jika Anda selalu khawatir tidak menambahkan perpustakaan untuk satu metode, tidak ada perpustakaan baru yang akan ditambahkan. Mengingat utilitas sangat baik hadir di Apache Commons, saya sangat merekomendasikan menambahkannya ketika use case pertama kali muncul.
Hindol
6
menggunakan apache commons tidak boleh disebut 'curang' saya mempertanyakan kewarasan pengembang yang hal itu merupakan ketergantungan yang tidak perlu.
Jeryl Cook
768

Berikut adalah metode sederhana yang akan menggabungkan dua array dan mengembalikan hasilnya:

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

Perhatikan bahwa itu tidak akan berfungsi dengan tipe data primitif, hanya dengan tipe objek.

Versi yang sedikit lebih rumit berikut ini berfungsi dengan array objek dan primitif. Itu melakukan ini dengan menggunakan Tbukan T[]sebagai tipe argumen.

Hal ini juga memungkinkan untuk menggabungkan array dari dua tipe yang berbeda dengan memilih tipe yang paling umum sebagai tipe komponen dari hasilnya.

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

Berikut ini sebuah contoh:

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
sumber
1
Saya suka saran ini karena kurang tergantung pada versi Java terbaru. Dalam proyek saya, saya sering terjebak menggunakan versi Java atau CLDC profil lama di mana beberapa fasilitas seperti yang disebutkan oleh Antti tidak tersedia.
kvn
4
Baris berikut akan memecah bagian generik: concatenate (new String [] {"1"}, Object baru [] {new Object ()})
dragon66
akan menyenangkan tidak harus menggunakan penjelasan @SuppressWarnings - Saya akan memposting solusi untuk itu di bawah ini.
beaudet
+1 untuk Array.newInstance(a.getClass().getComponentType(), aLen + bLen);. Secara mengejutkan saya belum pernah melihat itu sebelumnya. @beaudet Saya pikir penjelasannya baik-baik saja di sini, mengingat mengapa ini sedang ditekan.
Blake
1
ha, panggil saya purist tapi saya lebih suka kode bersih yang tidak memerlukan penindasan peringatan untuk menghapus peringatan
beaudet
475

Dimungkinkan untuk menulis versi sepenuhnya generik yang bahkan dapat diperluas untuk menggabungkan sejumlah array. Versi ini membutuhkan Java 6, seperti yang mereka gunakanArrays.copyOf()

Kedua versi menghindari membuat Listobjek perantara dan menggunakan System.arraycopy()untuk memastikan bahwa menyalin array besar secepat mungkin.

Untuk dua array terlihat seperti ini:

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

Dan untuk jumlah array yang arbitrer (> = 1) terlihat seperti ini:

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
sumber
10
@djBO: untuk array yang diketik primitif Anda harus membuat kelebihan untuk setiap jenis: cukup salin kode dan ganti masing T- masing dengan byte(dan kehilangan <T>).
Joachim Sauer
dapatkah Anda memberi tahu saya cara menggunakan jenis operator <T> di kelas saya?
Johnydep
6
Saya akan menambahkan ini ke awal, hanya untuk bersikap defensif. if (first == null) {if (second == null) {return null; } kembali kedua; } if (second == null) {return first; }
marathon
4
@ DjBo: bagaimana dengan:ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
Sam Goldberg
18
Ada bug dalam pendekatan ini yang menjadi jelas jika Anda memanggil fungsi-fungsi ini dengan array dari tipe komponen yang berbeda, misalnya concat(ai, ad), di mana aiada Integer[]dan adsekarang Double[]. (Dalam hal ini, parameter tipe <T>dipecahkan <? extends Number>oleh kompiler.) Array yang dibuat oleh Arrays.copyOfakan memiliki tipe komponen array pertama, yaitu Integerdalam contoh ini. Ketika fungsi akan menyalin array kedua, sebuah ArrayStoreExceptionakan dilempar. Solusinya adalah memiliki Class<T> typeparameter tambahan .
T-Bull
457

Menggunakan Streamdi Java 8:

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

Atau seperti ini, menggunakan flatMap:

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

Untuk melakukan ini untuk tipe generik Anda harus menggunakan refleksi:

@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
    size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));
Lii
sumber
28
Seberapa efisien ini?
Supuhstar
8
Layak dibaca: jaxenter.com/... tl; dr - stream dapat menjadi performant atau tidak, itu tergantung pada apa yang Anda lakukan dengan mereka dan kendala masalah (bukankah ini selalu jawabannya? Lol)
Trevor Brown
6
Selain itu, jika a atau b adalah array dari tipe primitif, stream mereka harus berupa .boxed()mereka yang Streambukan tipe misalnya IntStreamyang tidak dapat diteruskan sebagai parameter Stream.concat.
Will Hardwick-Smith
17
@ Will Hardwick-Smith: tidak, Anda hanya perlu memilih kelas aliran yang tepat, misalnya jika adan badalah int[], penggunaanint[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
Holger
3
@Supuhstar: Mungkin tidak secepat System.arrayCopy. Tapi tidak terlalu lambat juga. Anda mungkin harus melakukan ini sangat berkali-kali dengan besar array di benar-benar kinerja konteks sensitif untuk waktu eksekusi perbedaan untuk peduli.
Lii
191

Atau dengan Jambu kesayangan :

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

Juga, ada versi untuk array primitif:

  • 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
sumber
Saya suka Guava, metode dari Apache Commons lebih baik menangani nullables.
Ravi Wallau
7
Meskipun baik untuk menggunakan perpustakaan, sangat disayangkan bahwa masalahnya telah diabstraksi. Oleh karena itu solusi yang mendasarinya tetap sulit dipahami.
user924272
51
Apa masalahnya dengan abstraksi? Entah apa masalahnya dengan menciptakan kembali roda di sini, jika Anda ingin mempelajari masalahnya, periksa sumbernya atau bacalah. Kode profesional harus menggunakan perpustakaan tingkat tinggi, jauh lebih baik jika dikembangkan di dalam Google!
Breno Salgado
@RaviWallau Bisakah Anda menautkan ke kelas yang melakukan ini?
Sébastien Tromp
1
@ SébastienTromp Ini adalah solusi teratas untuk pertanyaan ini - ArrayUtils.
Ravi Wallau
70

Anda dapat menambahkan dua array dalam dua baris kode.

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

Ini adalah solusi cepat dan efisien dan akan bekerja untuk tipe primitif serta dua metode yang terlibat kelebihan beban.

Anda harus menghindari solusi yang melibatkan ArrayLists, stream, dll karena ini akan perlu mengalokasikan memori sementara tanpa tujuan yang bermanfaat.

Anda harus menghindari forloop untuk array besar karena ini tidak efisien. Metode bawaan menggunakan fungsi blok-salin yang sangat cepat.

rghome
sumber
1
Ini adalah salah satu solusi terbaik. 100% Java standar. Cepat / efisien. Harus mendapatkan lebih banyak upvotes!
Shebla Tsama
58

Menggunakan 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()]);
}
Fabian Steeg
sumber
13
Cukup, tetapi tidak efisien karena membuat array untuk ArrayList dan kemudian menghasilkan metode toArray lainnya. Tapi tetap valid karena mudah dibaca.
PhoneixS
1
berlaku untuk String dan objek (seperti yang diinginkan pertanyaan), tetapi tidak ada metode addAll untuk tipe primer (seperti int)
joro
Seperti yang diuraikan dalam artikel ini , menggunakan both.toArray(new String[0])akan lebih cepat daripada both.toArray(new String[both.size()]), bahkan jika itu bertentangan dengan intuisi naif kita. Itulah mengapa sangat penting untuk mengukur kinerja aktual saat mengoptimalkan. Atau cukup gunakan konstruk yang lebih sederhana, ketika keunggulan varian yang lebih rumit tidak dapat dibuktikan.
Holger
42

Solusi 100% java lama dan tanpa System.arraycopy (tidak tersedia di klien GWT misalnya):

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
sumber
Tambang ulang untuk File [], tapi itu sama. Terima kasih atas solusi Anda
ShadowFlame
5
Mungkin agak tidak efisien.
JonasCz
Anda mungkin ingin menambahkan nullcek. Dan mungkin mengatur beberapa variabel Anda final.
Tripp Kinetics
nullPemeriksaan @TrippKinetics akan menyembunyikan NPE daripada menunjukkannya dan menggunakan final untuk vars lokal tidak memiliki manfaat (belum).
Maarten Bodewes
1
@ Maarten Bodewes Saya pikir Anda akan menemukan (jika Anda membandingkannya, yang saya miliki) bahwa untuk masing-masing berjalan dalam waktu yang sama dengan loop yang diindeks pada versi terakhir Java. Pengoptimal merawatnya.
rghome
33

Saya baru-baru ini menghadapi masalah dengan rotasi memori yang berlebihan. Jika a dan / atau b diketahui umumnya kosong, berikut ini adalah adaptasi lain dari kode silvertab (dibuat juga):

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

Sunting: Versi sebelumnya dari posting ini menyatakan bahwa penggunaan ulang array seperti ini harus didokumentasikan dengan jelas. Seperti yang ditunjukkan oleh Maarten dalam komentar, secara umum akan lebih baik untuk menghapus pernyataan if, sehingga membatalkan kebutuhan untuk memiliki dokumentasi. Tetapi sekali lagi, pernyataan if adalah inti dari optimasi khusus ini. Saya akan meninggalkan jawaban ini di sini, tetapi berhati-hatilah!

voli
sumber
5
Namun ini berarti bahwa Anda mengembalikan array yang sama dan mengubah nilai pada array yang dikembalikan mengubah nilai di posisi yang sama dari array input yang dikembalikan.
Lorenzo Boccaccia
Ya - lihat komentar di akhir posting saya tentang penggunaan ulang array. Overhead pemeliharaan yang dikenakan oleh solusi ini sepadan dengan kasus kami, tetapi penyalinan defensif mungkin harus digunakan dalam kebanyakan kasus.
voli
Lorenzo / volley, dapatkah Anda menjelaskan bagian mana dari kode yang menyebabkan penggunaan ulang array? Saya pikir System.arraycopymenyalin isi array?
Rosdi Kasim
4
Penelepon biasanya mengharapkan panggilan ke concat () untuk mengembalikan array yang baru dialokasikan. Jika a atau b adalah null, concat () akan mengembalikan salah satu array yang dilewatkan ke dalamnya. Penggunaan kembali ini adalah apa yang mungkin tidak terduga. (Yap, arraycopy hanya melakukan penyalinan. Penggunaan kembali berasal dari mengembalikan a atau b secara langsung.)
volley
Kode harus sebanyak mungkin penjelasan sendiri. Orang yang membaca kode tidak harus mencari JavaDoc dari fungsi yang dipanggil untuk mengetahui bahwa ia melakukan satu hal untuk satu kondisi tertentu dan sesuatu yang lain untuk yang lain. Singkatnya: Anda biasanya tidak dapat memperbaiki masalah desain seperti ini dengan komentar. Menyingkirkan dua ifpernyataan saja merupakan cara yang paling mudah.
Maarten Bodewes
27

The Java Fungsional perpustakaan memiliki kelas wrapper array melengkapi array dengan metode berguna seperti Rangkaian.

import static fj.data.Array.array;

...lalu

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

Untuk mendapatkan kembali array yang terbuka, panggil

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

both.toArray(new String[0]);
nick-s
sumber
3
Jawabannya bagus tapi sedikit rusak. Untuk membuatnya sempurna, Anda harus meneruskan ke toArray () array dari jenis yang Anda butuhkan. Dalam contoh di atas, kode harus: both.toArray (new String [0]) Lihat: stackoverflow.com/questions/4042434/…
Ronen Rabinovici
Tidak tahu mengapa jawaban ini tidak diberi peringkat lebih tinggi ... meskipun tampaknya perlu perubahan yang disarankan oleh @RonenRabinovici
drmrbrewer
4
Atau lebih baik, tanpa alokasi array nol-panjang yang tidak perlu both.toArray(new String[both.size()])
:;
1
@Honza merekomendasikan baca
Holger
Hai @Honza, mungkin untuk melakukan hal yang sama untuk mengembalikan array integer primitif dalam 3 baris?
jumping_monkey
18

Cara lain dengan Java8 menggunakan 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
sumber
17

Berikut ini adalah adaptasi dari solusi silvertab, dengan obat generik yang dilengkapi:

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

CATATAN: Lihat jawaban Joachim untuk solusi Java 6. Tidak hanya menghilangkan peringatan; juga lebih pendek, lebih efisien, dan lebih mudah dibaca!

voli
sumber
Anda dapat menekan peringatan untuk metode ini, tetapi selain itu tidak banyak yang dapat Anda lakukan. Array dan obat generik tidak benar-benar bercampur.
Dan Dyer
3
Peringatan yang tidak dicentang dapat dihilangkan jika Anda menggunakan Arrays.copyOf (). Lihat jawaban saya untuk implementasi.
Joachim Sauer
@SuppressWarnings ("tidak dicentang")
Mark Renouf
13

Jika Anda menggunakan cara ini maka Anda tidak perlu mengimpor kelas pihak ketiga mana pun.

Jika Anda ingin menyatukan String

Kode sampel untuk dua String Array

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

Jika Anda ingin menyatukan Int

Kode sampel untuk dua bilangan bulat Integer

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

Berikut adalah metode Utama

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

        }
    }  

Kita bisa menggunakan cara ini juga.

Raj S. Rusia
sumber
11

Maafkan saya karena telah menambahkan versi lain ke daftar yang sudah lama ini. Saya melihat setiap jawaban dan memutuskan bahwa saya benar-benar menginginkan versi dengan hanya satu parameter di tanda tangan. Saya juga menambahkan beberapa pemeriksaan argumen untuk mendapatkan manfaat dari kegagalan awal dengan info yang masuk akal jika input tidak terduga.

@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
sumber
Saya akan meringkas panjangnya dalam loop yang sama di mana Anda melakukan pemeriksaan nol - tetapi ini adalah ringkasan yang sangat bagus dari jawaban lain di sini. Saya percaya ini bahkan menangani tipe intrinsik seperti "int" tanpa mengubahnya menjadi objek Integer yang benar-benar satu-satunya alasan untuk berurusan dengan mereka sebagai array daripada hanya mengubah segalanya menjadi ArrayLists. Juga metode Anda dapat mengambil 2 array dan parameter (...) sehingga pemanggil tahu ia harus memasukkan setidaknya dua array sebelum ia menjalankannya dan melihat kesalahan, tetapi itu menyulitkan kode pengulangan ....
Bill K
11

Anda dapat mencoba mengubahnya menjadi Arraylist dan menggunakan metode addAll kemudian mengonversi kembali ke array.

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();
Paul
sumber
Solusi yang bagus - akan lebih baik jika kode itu direactored untuk menghindari array yang mendukung ArrayLists, tetapi itu di luar kendali "Jawab" dan sampai ke penanya.
Bill K
Saya menghitung bahwa itu membutuhkan 4 objek sementara tambahan untuk bekerja.
rghome
@rghome, setidaknya tidak memerlukan pustaka tambahan untuk mengimplementasikan tugas semudah itu
Farid
9

Menggunakan aliran Java 8+ Anda dapat menulis fungsi berikut:

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

Di sini kemungkinan implementasi dalam kode kerja dari solusi kode semu yang ditulis oleh silvertab.

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

Mengikuti selanjutnya adalah antarmuka pembangun.

Catatan: Builder diperlukan karena di java tidak mungkin dilakukan

new T[size]

karena penghapusan tipe generik:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

Di sini pembangun beton mengimplementasikan antarmuka, membangun sebuah Integerarray:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

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

Dan akhirnya aplikasi / tes:

@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
sumber
7

Ini harus satu baris.

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

Wow! banyak jawaban kompleks di sini termasuk beberapa jawaban sederhana yang bergantung pada dependensi eksternal. bagaimana kalau melakukannya seperti ini:

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]);
sedekah
sumber
1
..Tapi tidak efisien dan lambat.
JonasCz
6

Ini berfungsi, tetapi Anda harus memasukkan pemeriksaan kesalahan Anda sendiri.

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

Ini mungkin bukan yang paling efisien, tetapi tidak bergantung pada apa pun selain API Java sendiri.

72%
sumber
2
+1. Akan lebih baik untuk mengganti forloop kedua dengan itu:for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
bancer
Gunakan String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)untuk melewati forloop pertama . Menghemat waktu sebanding dengan ukuran arr1.
John Meyer
5

Ini adalah fungsi yang dikonversi untuk array 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
sumber
5

Bagaimana dengan sederhana

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

Dan lakukan saja Array.concat(arr1, arr2). Selama arr1dan arr2dari jenis yang sama, ini akan memberi Anda array lain dari jenis yang sama yang mengandung kedua array.

Efraim
sumber
Untuk alasan kinerja, saya akan melakukan pra-komputasi ukuran akhir ArrayList karena ArrayList, menurut definisi, mengalokasikan array baru dan menyalin elemen-elemennya setiap kali array saat ini penuh. Kalau tidak, saya akan langsung menuju LinkedList yang tidak mengalami masalah seperti itu
usr-local-ΕΨΗΕΛΩΝ
5

Versi statis umum yang menggunakan System.arraycopy berkinerja tinggi tanpa memerlukan anotasi @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
sumber
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
sumber
4

Ini adalah versi saya yang sedikit lebih baik dari concatAll Joachim Sauer. Ini dapat bekerja pada Java 5 atau 6, menggunakan System.arraycopy Java 6 jika tersedia saat runtime. Metode ini (IMHO) sangat cocok untuk Android, karena bekerja pada Android <9 (yang tidak memiliki System.arraycopy) tetapi akan menggunakan metode yang lebih cepat jika memungkinkan.

  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
sumber
1
Ide umum yang bagus, tetapi untuk siapa pun yang menerapkan: Saya lebih suka versi copyOf dan non-copyOf daripada yang melakukan keduanya dengan cara refleksi.
rektide
4

Cara lain untuk memikirkan pertanyaan itu. Untuk menggabungkan dua array atau lebih, yang harus dilakukan adalah membuat daftar semua elemen dari setiap array, dan kemudian membangun array baru. Ini terdengar seperti membuat List<T>dan kemudian memanggilnya toArray. Beberapa jawaban lain digunakan ArrayList, dan itu tidak masalah. Tetapi bagaimana dengan mengimplementasikan kita sendiri? Itu tidak sulit:

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

Saya percaya hal di atas setara dengan solusi yang digunakan System.arraycopy. Namun saya pikir yang ini memiliki keindahannya sendiri.

Mesin Tanah
sumber
4

Bagaimana tentang :

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
sumber
4

Variasi sederhana yang memungkinkan penggabungan lebih dari satu array:

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
sumber
3

Hanya menggunakan API milik 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]);
}

Sekarang, kode ini bukan yang paling efisien, tetapi hanya bergantung pada kelas-kelas java standar dan mudah dimengerti. Ini berfungsi untuk sejumlah String [] (bahkan nol array).

Kiwi
sumber
15
Harus downvote yang ini untuk semua pembuatan objek Daftar yang tidak perlu.
Outlaw Programmer