Java'da iki diziyi nasıl birleştirebilirim?


1366

StringJava'da iki diziyi birleştirmem gerekiyor .

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

Bunu yapmanın en kolay yolu nedir?


3
Guava'dan Bytes.concat
Ben Sayfa

1
Burada tepkilerin çok görmek ama soru yüzden ( 'kolay yolu'?) O iyi cevabı ... göstermek için izin vermediğini ifadeli edilir
Artur Opalinski

2
Burada onlarca cevap, verileri yeni bir diziye kopyalıyor çünkü istenen şey bu - ama kesinlikle gerekli olmadığında veri kopyalamak özellikle Java'da yapmak kötü bir şey. Bunun yerine, dizinleri takip edin ve iki diziyi birleştirilmiş gibi kullanın. Tekniği gösteren bir çözüm ekledim.
Douglas

12
Şu anda böyle bir sorunun 50 farklı cevabı olması, Java'nın neden basit bir array1 + array2birleşim elde etmediğini merak ediyor .
JollyJoker

2
Standart Java'nın iki satırında mükemmel bir şekilde ve çok verimli bir şekilde yapabilirsiniz (cevabıma bakın), bu yüzden bunu yapmak için tek bir yöntemle elde edilecek korkunç bir şey yoktur. Tüm bu garip ve harika çözümler biraz zaman kaybı.
rghome

Yanıtlar:


1093

Eski Apache Commons Lang kütüphanesinden tek satırlık bir çözüm buldum.
ArrayUtils.addAll(T[], T...)

Kod:

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

175
Soruyu cevaplarsa nasıl "aldatma" olur? Tabii ki, ekstra bir bağımlılığa sahip olmak muhtemelen bu özel durum için aşırı derecede doludur, ancak özellikle Apache Commons'ta çok fazla mükemmel işlevsellik parçası olduğu için var olduğunu söylemeye hiçbir zarar verilmez.
Rob

33
Katılıyorum, bu gerçekten soruyu cevaplamıyor. Üst düzey kütüphaneler harika olabilir, ancak bunu yapmak için etkili bir yol öğrenmek istiyorsanız, kütüphane yönteminin kullandığı koda bakmak istersiniz. Ayrıca, birçok durumda, üründeki başka bir kütüphane aracılığıyla anında hareket edemezsiniz.
AdamC

76
Bence bu iyi bir cevap. POJO çözümleri de sağlanmıştır, ancak OP programlarında zaten Apache Commons kullanıyorsa (popülaritesi göz önüne alındığında tamamen mümkündür) bu çözümü hala bilmiyor olabilir. O zaman "bu yöntem için bir bağımlılık eklemek" olmaz, ancak mevcut bir kütüphaneyi daha iyi kullanırdı.
Adam

14
Her zaman tek bir yöntem için kitaplık eklememekten endişe ediyorsanız, hiçbir yeni kitaplık eklenmeyecektir. Apache Commons'ta bulunan mükemmel yardımcı programlar göz önüne alındığında, ilk kullanım durumu ortaya çıktığında eklemenizi şiddetle tavsiye ederim.
Hindol

6
apache müştereklerini kullanmak asla 'aldatma' olarak adlandırılmamalıdır.
Jeryl Cook

768

İki diziyi birleştirecek ve sonucu döndürecek basit bir yöntem:

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

İlkel veri türleriyle değil, yalnızca nesne türleriyle çalışmayacağını unutmayın.

Aşağıdaki biraz daha karmaşık sürüm hem nesne hem de ilkel dizilerle çalışır. Bu kullanarak gerçekleştirir Tyerine T[]argüman türü olarak.

Ayrıca, sonucun bileşen türü olarak en genel türü seçerek iki farklı türden dizileri birleştirmeyi de mümkün kılar.

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

İşte bir örnek:

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

1
En son Java sürümlerine daha az bağımlı olduğu için bu öneriyi beğendim. Projelerimde genellikle Antti'nin bahsettiği gibi bazı olanakların bulunmadığı Java veya CLDC profillerinin eski sürümlerini kullanıyorum.
kvn

4
Aşağıdaki satır genel bölümü
kıracaktır

@SuppressWarnings ek açıklamasını kullanmak zorunda kalmamanız iyi olur - bunun için bir çözüm göndereceğim.
beaudet

İçin +1 Array.newInstance(a.getClass().getComponentType(), aLen + bLen);. Daha önce hiç görmedim. @beaudet Bence bu açıklama, neden bastırıldığını düşünüyor.
Blake

1
ha, bana bir
safkan deyin ama

475

İstediğiniz sayıda diziyi birleştirmek için genişletilebilecek tamamen genel bir sürüm yazmak mümkündür. Bu sürümler kullandıkları için Java 6 gerektirirArrays.copyOf()

Her iki sürüm de ara Listnesneler oluşturmaktan kaçınır ve System.arraycopy()büyük dizileri kopyalamanın mümkün olduğunca hızlı olmasını sağlamak için kullanılır.

İki dizide şöyle görünür:

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

Ve rastgele sayıda dizi için (> = 1) şöyle görünür:

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

10
@djBO: Sadece kodu kopyalayıp ve her değiştirin: ilkel-daktilo diziler için her türü için bir aşırı yapmak gerekiyordu Tile byte(ve kaybetmek <T>).
Joachim Sauer

Bana sınıfımda <T> operatör türünü nasıl kullanacağımı söyleyebilir misin?
Johnydep

6
Bunu başlangıçta eklerdim, sadece savunmacı olmak için. if (first == null) {if (second == null) {dönüş null; } ikinci dönüş; } if (second == null) {önce dön; }
maraton

4
@djBo: ne hakkında:ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
Sam Goldberg

18
Örneğin, farklı bileşen türleri dizileri ile bu fonksiyonları çağırmak durumunda belirgin hale gelir bu yaklaşımda bir hata var concat(ai, ad), nerede aiolduğunu Integer[]ve adbir Double[]. (Bu durumda, type parametresi derleyici tarafından <T>çözümlenir <? extends Number>.) Tarafından oluşturulan Arrays.copyOfdizi, ilk dizinin bileşen türüne (yani Integerbu örnekte) sahip olacaktır. İşlev ikinci diziyi kopyalamak üzereyken, bir ArrayStoreExceptionatılır. Çözüm, ek bir Class<T> typeparametreye sahip olmaktır .
T-Bull

457

StreamJava 8'de kullanma :

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

Ya da şunu kullanarak flatMap:

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

Bunu genel bir tür için yapmak için yansıma kullanmanız gerekir:

@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
    size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));

28
Bu ne kadar verimli?
Supuhstar

8
Okumaya değer: jaxenter.com/… tl; dr - akışlar performans gösterip göstermeyebilir, onlarla ne yaptığınıza ve sorunun kısıtlamalarına bağlıdır (bu her zaman cevap değil mi? Lol)
Trevor Brown

6
Ek olarak, a veya b , ilkel tipteki dizilerse, akışlarının, örneğin bir parametre olarak iletilemeyen .boxed()türden Streamziyade türden IntStreamolması gerekir Stream.concat.
Will Hardwick-Smith

17
@Will Hardwick-Smith: hayır, sadece sağ akışı sınıfını, örneğin eğer almak zorunda ave bvardır int[], kullanımıint[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
Holger

3
@Supuhstar: Muhtemelen o kadar hızlı değil System.arrayCopy. Ama özellikle yavaş değil. Muhtemelen bunu yapmak zorunda çok sahip birçok kez büyük diziler gerçekten maddeye yürütme zamanı farkı performans duyarlı bağlamlarda.
Lii

191

Veya sevgili Guava ile :

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

Ayrıca, ilkel diziler için sürümler vardır:

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

Guava'yı sevdiğim kadar, Apache Commons'ın yöntemi nullables ile daha iyi ilgileniyor.
Ravi Wallau

7
Kütüphaneleri kullanmak iyi olsa da, sorunun soyutlanması talihsiz bir durumdur. Bu nedenle altta yatan çözüm anlaşılması zor.
user924272

51
Soyutlama ile ilgili sorun nedir? Burada tekerleği yeniden icat etmenin ne anlama geldiğini öğrenin, eğer problemi öğrenmek istiyorsanız kaynağı kontrol edin ya da okuyun. Profesyonel kod, Google içinde geliştirilmişse daha yüksek seviyeli kitaplıklar kullanıyor olmalıdır!
Breno Salgado

@RaviWallau Bunu yapan sınıfa bağlanabilir misiniz?
Sébastien Tromp

1
@ SébastienTromp Bu soru için en iyi çözüm - ArrayUtils.
Ravi Wallau

70

İki diziyi iki kod satırına ekleyebilirsiniz.

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

Bu hızlı ve verimli bir çözümdür ve ilkel tipler için işe yarayacak ve ilgili iki yöntem aşırı yüklenecektir.

ArrayLists, stream, vb. İçeren çözümlerden kaçınmalısınız, çünkü bunların faydalı bir amaç için geçici bellek ayırması gerekir.

forVerimli olmadığı için büyük diziler için döngülerden kaçınmalısınız . Yerleşik yöntemler son derece hızlı olan blok kopyalama işlevlerini kullanır.


1
Bu en iyi çözümlerden biridir. % 100 standart Java. Hızlı / etkili. Daha fazla oy almalı!
Shebla Tsama

58

Java API'sini kullanma:

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

13
Basitçe, ama ArrayList için bir dizi yapmak ve daha sonra toArray yöntemi için başka bir dizi oluşturmak gibi verimsiz. Ancak okunması kolay olduğu için hala geçerlidir.
PhoneixS

1
Yaylı ve nesneler (soru istediği gibi) için geçerli, ama (ints gibi) birincil türleri için hiçbir addAll yöntemi yoktur
joro

As detaylandırılan bu makalede kullanarak both.toArray(new String[0])daha hızlı olacak both.toArray(new String[both.size()])bizim naif sezgi çelişse bile. Bu nedenle optimizasyon sırasında gerçek performansı ölçmek çok önemlidir. Veya daha karmaşık varyantın avantajı kanıtlanamadığında daha basit yapıyı kullanın.
Holger

42

% 100 eski java ve içermeyen bir çözüm System.arraycopy(örneğin GWT istemcisinde mevcut değildir):

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

Dosya [] için benimkini yeniden çalıştı, ancak aynı. Çözümünüz için teşekkürler
ShadowFlame

5
Muhtemelen oldukça verimsiz.
JonasCz - Monica'yı eski durumuna döndür

nullÇek eklemek isteyebilirsiniz . Ve belki de bazı değişkenlerinizi olarak ayarlayın final.
Tripp Kinetiği

@TrippKinetics nullkontrolleri, NPE'leri göstermek yerine gizleyecek ve yerel değişkenler için final kullanmanın herhangi bir faydası yok (henüz).
Maarten Bodewes

1
@Maarten Bodewes Bence her birinin Java'nın geç sürümlerinde dizinlenmiş döngü ile aynı zamanda çalıştığını (sahip olduğumu kıyaslarsanız) bulacaksınız. Optimize edici bununla ilgilenir.
rghome

33

Son zamanlarda aşırı bellek döndürme ile ilgili sorunlar yaşadım. A ve / veya b'nin yaygın olarak boş olduğu biliniyorsa, burada silvertab kodunun başka bir uyarlaması da vardır (ayrıca üretilmiştir):

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

Düzenleme: Bu yazının önceki bir sürümü, bunun gibi dizi yeniden kullanımının açıkça belgeleneceğini belirtti. Maarten yorumlarda belirtildiği gibi, genel olarak if ifadelerini kaldırmak daha iyi olur, böylece belgelere sahip olma ihtiyacını ortadan kaldırır. Ama yine de, eğer if ifadeleri ilk başta bu özel optimizasyonun bütün noktasıydı. Bu cevabı burada bırakacağım ama dikkatli ol!


5
ancak bu, aynı diziyi döndürdüğünüz ve döndürülen dizideki bir değeri değiştirdiğinizde, döndürülen giriş dizisinin aynı konumundaki değeri değiştirdiğiniz anlamına gelir.
Lorenzo Boccaccia

Evet - dizinin yeniden kullanımı ile ilgili gönderimin sonundaki açıklamaya bakın. Bu çözümün getirdiği bakım yükü bizim özel durumumuzda buna değdi, ancak çoğu durumda savunma amaçlı kopyalama muhtemelen kullanılmalıdır.
Voleybolu

Lorenzo / volley, kodda dizi yeniden kullanımına neden olan kısmı açıklayabilir misiniz? Ben System.arraycopydizinin içeriğini kopya düşündüm ?
Rosdi Kasım

4
Bir arayan normalde concat () çağrısının yeni atanan bir diziyi döndürmesini bekler. A veya b boşsa, concat (), içine geçirilen dizilerden birini döndürür. Bu yeniden kullanım beklenmedik bir şeydir. (Evet, dizikopi sadece kopyalama yapar. Yeniden kullanım a veya b'yi doğrudan döndürmekten gelir.)
voleybolu

Kod mümkün olduğunca kendi kendini açıklayıcı olmalıdır. Kodu okuyan kişilerin, belirli bir koşul için bir şey ve başka bir şey için başka bir şey yaptığını bulmak için çağrılan bir işlevin JavaDoc'unu araması gerekmez. Kısacası: genellikle böyle tasarım problemlerini bir yorum ile çözemezsiniz. İki ififadeyi dışarıda bırakmak en kolay çözüm olacaktır.
Maarten Bodewes

27

Fonksiyonel Java kütüphanesi birleştirme gibi kullanışlı yöntemlerle diziler donatır bir dizi sarıcı sınıfı vardır.

import static fj.data.Array.array;

...ve sonra

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

Açılmamış diziyi geri almak için arayın

String[] s = both.array();

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

both.toArray(new String[0]);

3
Cevap harika ama biraz kırılmış. Mükemmel hale getirmek için ihtiyacınız olan türde bir dizi toArray () 'a geçmelisiniz. Yukarıdaki örnekte, kod şöyle olmalıdır: both.toArray (yeni Dize [0]) Bkz: stackoverflow.com/questions/4042434/…
Ronen Rabinovici

Bu cevabın neden daha yüksek derecelendirilmediğini bilmiyorum ... @RonenRabinovici tarafından önerilen değişikliğe ihtiyacı var gibi görünüyor
drmrbrewer

4
Ya da daha iyisi, sıfır uzunluklu dizinin gereksiz tahsisi olmadan both.toArray(new String[both.size()]):;)
Honza

1
@Honza önerilir
Holger

Merhaba @Honza, aynı 3 satırda bir ilkel tamsayı dizisi döndürmek mümkün mü?
jumping_monkey

18

Stream kullanarak Java8 ile başka bir yol

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

17

İşte silvertab'ın çözümünün, jenerikler sonradan uyarlanmış bir uyarlaması:

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

NOT: Java 6 çözümü için Joachim'in cevabına bakın . Sadece uyarıyı ortadan kaldırmaz; ayrıca daha kısa, daha verimli ve okunması daha kolay!


Bu yöntem için uyarıyı bastırabilirsiniz, ancak bunun dışında yapabileceğiniz çok şey yoktur. Diziler ve jenerikler gerçekten karışmıyor.
Dan Dyer

3
Arrays.copyOf () kullanırsanız denetlenmeyen uyarı ortadan kaldırılabilir. Bir uygulama için cevabımı görün.
Joachim Sauer

@SuppressWarnings ("işaretlenmemiş")
Mark Renouf

13

Bu şekilde kullanırsanız, herhangi bir üçüncü taraf sınıfını içe aktarmanıza gerek yoktur.

Birleştirmek istiyorsanız String

Eşdeğer iki Dize Dizisi için örnek kod

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

Birleştirmek istiyorsanız Int

Eşdeğer iki Tamsayı Dizisi için örnek kod

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

İşte Ana yöntem

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

        }
    }  

Bu şekilde de kullanabiliriz.


11

Lütfen zaten uzun olan bu listeye başka bir sürüm daha eklediğiniz için beni affedin. Her cevaba baktım ve imzada sadece bir parametreli bir versiyon istediğime karar verdim. Ayrıca beklenmedik bir girdi olması durumunda mantıklı bilgi ile erken başarısızlıktan yararlanmak için bazı argüman kontrolü ekledim.

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

Ben null kontrol yaptığınız aynı döngüde uzunluğu özetlemek istiyorum - ama bu burada diğer cevapların gerçekten iyi bir özetidir. Hatta "int" gibi intrinsik türleri, tamsayı nesnelere değiştirmeden bile işlediğine inanıyorum ki bu, her şeyi ArrayLists olarak değiştirmek yerine onlarla diziler olarak ele almanın tek nedenidir. Ayrıca yönteminiz 2 diziyi ve (...) parametresini alabilir, böylece arayan onu çalıştırmadan önce en az iki diziyi geçmesi gerektiğini bilir ve hatayı görür, ancak bu döngü kodunu zorlaştırır ....
Bill K

11

Bunu bir Arraylist'e dönüştürmeyi deneyebilir ve addAll yöntemini kullanarak bir diziye geri dönüştürebilirsiniz.

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();

İyi bir çözüm - ArrayLists lehine dizilerden tamamen kaçınmak için kodun yeniden düzenlenmesi daha iyi olurdu, ancak bu "Cevap" kontrolünün dışında ve sorgulayana kadar.
Bill K

Çalışmak için 4 ek geçici nesne gerektirdiğini sayıyorum.
rghome

@rghome, en azından böyle basit bir görevi yerine getirmek için ek kütüphane gerektirmez
Farid

9

Java 8+ akışlarını kullanarak aşağıdaki işlevi yazabilirsiniz:

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

7

Burada silvertab tarafından yazılan sözde kod çözümünün çalışma kodunda olası bir uygulama.

Teşekkürler 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;
   }
}

Sırada builder arayüzü var.

Not: Bir inşaatçı gereklidir, çünkü java'da yapmak mümkün değildir

new T[size]

genel tip silme nedeniyle:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

Burada, bir Integerdizi oluşturan arayüzü uygulayan somut bir üretici :

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

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

Ve son olarak uygulama / 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]);
   }
}

7

Bu bir astar olmalı.

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

6

Vaov! dış bağımlılıklara bağlı bazı basit cevaplar da dahil olmak üzere birçok karmaşık cevap burada. böyle yapmaya ne dersin:

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

1

6

Bu işe yarar, ancak kendi hata denetiminizi eklemeniz gerekir.

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

Muhtemelen en verimli değildir, ancak Java'nın kendi API'sından başka bir şeye güvenmez.


2
+1. İkinci fordöngüyü bununla değiştirmek daha iyi olurdu :for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
bancer

String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)İlk fordöngüyü atlamak için kullanın . Boyutuyla orantılı zaman kazandırır arr1.
John Meyer

5

Bu, bir String dizisi için dönüştürülmüş bir işlevdir:

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

Basitçe

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

Ve sadece yap Array.concat(arr1, arr2). arr1Ve arr2aynı türde olduğu sürece , bu size her iki diziyi içeren aynı türde başka bir dizi verecektir.


Performans nedenlerinden ötürü, ArrayList'in tanım gereği yeni bir dizi ayırdığı ve geçerli dizi her dolduğunda öğelerini kopyaladığı için ArrayList'in son boyutunu önceden hesaplayacağım. Aksi takdirde böyle bir sorun çekmeyen LinkedList için düz gitmek istiyorum
çekmeyen

5

@SuppressWarnings ek açıklamasına gerek duymadan yüksek performanslı System.arraycopy kullanan genel bir statik sürüm:

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

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

4

İşte Joachim Sauer'ın concatAll'ın biraz geliştirilmiş sürümü. Java 6 veya System.arraycopy kullanarak çalışma zamanında varsa Java 5 veya 6 üzerinde çalışabilir. Bu yöntem (IMHO) Android için mükemmeldir, çünkü Android <9'da (System.arraycopy içermeyen) çalışır, ancak mümkünse daha hızlı yöntemi kullanır.

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

1
İyi bir genel fikir, ama uygulayan herkese: Her ikisi de yansıma yoluyla yapan bir copyOf ve copyOf olmayan sürümleri tercih ederim.
rektide

4

Soru hakkında düşünmenin başka bir yolu. İki veya daha fazla diziyi birleştirmek için tek yapmanız gereken her dizinin tüm öğelerini listelemek ve sonra yeni bir dizi oluşturmaktır. Bu bir a oluşturmak gibi geliyor List<T>ve sonra çağırır toArray. Diğer bazı cevaplar kullanır ArrayListve bu iyi. Peki ya kendimizi uygulamaya ne dersiniz? Zor değil:

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

Yukarıdakilerin, kullanılan çözümlere eşdeğer olduğuna inanıyorum System.arraycopy. Ancak bunun kendi güzelliği olduğunu düşünüyorum.


4

Nasıl olur:

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

Birden fazla dizinin birleştirilmesine izin veren basit bir varyasyon:

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

3

Yalnızca Javas kendi API'sını kullanma:


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

Şimdi, bu kod en verimli değildir, ancak sadece standart java sınıflarına dayanır ve anlaşılması kolaydır. Herhangi bir sayıda String [] (sıfır dizi bile) için çalışır.


15
Tüm gereksiz List nesnesi oluşturma için bu bir aşağıya vardı.
Yasadışı Programcı
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.