Как я могу объединить два массива в Java?


1,071

Мне нужно объединить два массива String в Java.

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

Что является самым простым способом сделать это?

+1

Bytes.concat от Guava 15 мар. 162016-03-15 11:27:12

+1

Я вижу много ответов здесь, но вопрос так сформулирован («самый простой способ»?), Что он не позволяет указать лучший ответ ... 15 май. 162016-05-15 03:36:59

+2

Десятки ответов здесь копируют данные в новый массив, потому что это то, о чем просили, - но копирование данных, когда это строго необходимо, - это плохо, особенно в Java. Вместо этого отслеживайте индексы и используйте два массива, как если бы они были соединены. Я добавил решение, иллюстрирующее эту технику. 04 сен. 162016-09-04 23:34:53

  0

Простейшим является то, что вы, вероятно, не должны использовать массивы в первую очередь, вы должны использовать ArrayLists, а ваш вывод должен быть ArrayList. После того, как вы сделали это предварительное условие, операция будет встроена - first.addAll (вторая). Единственный случай, когда это не было бы довольно автоматическим, - это когда ваши массивы не являются объектными типами (int, long, double, ...), в этом случае внутренние массивы могут иметь большое преимущество перед ArrayLists, но для строк --meh 15 авг. 172017-08-15 16:27:23

+1

Тот факт, что такой вопрос в настоящее время имеет 50 различных ответов, заставляет меня задаться вопросом, почему Java никогда не получала простой конкатенации «array1 + array2». 28 ноя. 172017-11-28 12:53:42

696

Вот простой метод, который будет объединять два массива и возвращает результат:

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

Примечание, как это не будет работать с примитивами, только с типами объектов.

Следующая несколько более сложная версия работает как с объектным, так и с примитивным массивом. Он делает это, используя T вместо T[] в качестве типа аргумента.

Он также позволяет объединять массивы двух разных типов, выбирая наиболее общий тип в качестве типа компонента результата.

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

Вот пример:

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

Мне нравится это предложение, так как оно в меньшей степени зависит от последних версий Java. В моих проектах я часто застрял, используя старые версии профилей Java или CLDC, где некоторые из объектов, подобных упомянутым Antti, недоступны. 07 фев. 112011-02-07 15:46:33

+3

Следующая строка разбивает общую часть: concatenate (new String [] {"1"}, новый Object [] {new Object()}) 03 июн. 152015-06-03 02:09:19


883

Я нашел решение одной строки из старой хорошей библиотеки Apache Commons Lang.
ArrayUtils.addAll(T[], T...)

Код:

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

Я не знаю, это своего рода обман. Я думаю, что большинству людей, вероятно, не понадобится дополнительная зависимость для этого метода. 23 сен. 082008-09-23 19:15:15

+128

Как это «обманывает», если он отвечает на вопрос? Конечно, наличие дополнительной зависимости, вероятно, слишком велико для этой конкретной ситуации, но никакого вреда в том, что она существует, тем более, что в Apache Commons так много прекрасных функций. 12 окт. 082008-10-12 15:58:35

+28

Согласен, это на самом деле не отвечает на вопрос. Библиотеки высокого уровня могут быть отличными, но если вы хотите изучить эффективный способ сделать это, вы хотите посмотреть на код, который использует библиотечный метод.Кроме того, во многих ситуациях вы не можете просто через другую библиотеку в продукте «на лету». 18 июн. 092009-06-18 17:09:19

+60

Я думаю, что это хороший ответ. Также были предоставлены решения POJO, но если OP уже использует Apache Commons в своей программе (возможно, учитывая его популярность), он все еще может не знать этого решения. Тогда он не будет «добавлять зависимость для этого метода», но будет лучше использовать существующую библиотеку. 17 ноя. 092009-11-17 15:36:52

+1

@ Outlaw Programmer, я думаю, что большинство людей предпочитают простейший возможный метод. Java уже достаточно подробно. 26 ноя. 102010-11-26 22:35:18

+13

Как отметил @ Kutzi ниже, это даже не компилируется, потому что не существует метода 'addAll()', который возвращает 'String []'. 01 дек. 102010-12-01 15:17:54

+3

Я использую commons-lang-2.4.jar. В ArrayUtils нет общей версии addAll(). Поэтому я должен был явно вернуть возвращенный Object [] в String []. 17 май. 122012-05-17 11:33:43

  0

, вы могли бы дать ссылку на ответ так же, как и вы, и вставить реализацию из источника. что позволило бы решить вышеперечисленные проблемы об «обмане» аспекта вашего ответа. 03 май. 132013-05-03 15:33:21

+4

ОП запросил самый простой способ решить проблему. Это самый простой способ, но только в предположении, что библиотека уже присутствует, что не упоминается в вопросе. В противном случае на самом деле гораздо проще копировать и вставлять несколько строк кода вместо копирования только одного, а затем возиться с добавлением отдельной библиотеки в проект. 12 июл. 132013-07-12 21:51:50

+7

Если вы всегда беспокоитесь о том, что не добавляете библиотеку для одного метода, новые библиотеки никогда не будут добавлены. Учитывая отличные утилиты, присутствующие в Apache Commons, я настоятельно рекомендую добавить его, когда возникает первый случай использования. 25 июн. 152015-06-25 08:46:53

  0

Я не могу найти аналогичный метод для коллекций 18 мар. 162016-03-18 14:41:54

  0

@ Аннет Сикари извините за вопрос Я новичок в Java, почему '' (String []) 'используется в' String [] both = (String []) ArrayUtils.addAll (первый, второй); 'без него он не будет объединять 2 массива 06 июн. 162016-06-06 07:41:53

+1

, используя apache commons, никогда не следует называть« обманывать », я сомневаюсь в здравом рассудке разработчиков, которые считают его ненужной зависимостью. 05 июл. 162016-07-05 20:06:06

  0

ArrayUtils можно скачать по адресу http://commons.apache.org/proper/commons-lang/download_lang.cgi 11 авг. 162016-08-11 07:36:38

  0

Я всегда забываю об Apache commons ArrayUtils и благодарен за напоминание! 25 окт. 172017-10-25 18:11:30


25

Functional Java библиотека имеет класс-оболочки массива, экипирование массивов с удобными методами, как конкатенация.

import static fj.data.Array.array; 

... а затем

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

Чтобы получить развернутый массив обратно, вызовите

String[] s = both.array(); 

4

Использование только Javas собственный API:


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

Теперь, этот код не самый эффективный, но он полагается только на на стандартных классах Java и легко понять. Он работает для любого числа String [] (даже нулевые массивы).

+14

Пришлось использовать это для всего ненужного создания объекта списка. 23 сен. 082008-09-23 19:23:59


17

Вот адаптация решения silvertab, в генериков модернизированы:

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

ПРИМЕЧАНИЕ: См Joachim's answer для решения Java 6. Это не только устраняет предупреждение; он также короче, эффективнее и легче читать!

  0

Вы можете подавить предупреждение для этого метода, но кроме этого вы не можете многое сделать. Массивы и дженерики на самом деле не смешиваются. 25 сен. 082008-09-25 19:43:21

+3

Неконтролируемое предупреждение может быть устранено, если вы используете Arrays.copyOf(). См. Мой ответ для реализации. 24 апр. 092009-04-24 07:30:19

  0

@SuppressWarnings («unchecked») 26 апр. 092009-04-26 19:21:10


29

Я недавно сталкивался с проблемами с чрезмерным вращением памяти. Если и/или б, как известно, обычно пустой, вот еще подстройка кода silvertab (в обобщен тоже):

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

(В любом случае, массив поведение повторного использования должны быть четко JavaDoced!)

+4

это, однако, означает, что вы возвращаете один и тот же массив, а изменение значения возвращаемого массива меняет значение в той же позиции возвращаемого массива. 26 ноя. 082008-11-26 17:55:52

  0

Да - см. Комментарий в конце моего сообщения о повторном использовании массива. Накладные расходы на обслуживание, наложенные этим решением, стоили этого в нашем конкретном случае, но в большинстве случаев необходимо использовать защитное копирование. 17 мар. 092009-03-17 14:43:21

  0

Лоренцо/волейбол, можете ли вы объяснить, какая часть кода вызывает повторное использование массива? Я думал, что 'System.arraycopy' копирует содержимое массива? 13 май. 102010-05-13 02:35:30

+4

Обычно вызывающий абонент ожидает вызова concat() для возврата вновь выделенного массива. Если a или b равно null, concat(), однако, вернет один из массивов, переданных в него. Это повторное использование является неожиданным. (Yep, arraycopy только копирует. Повторное использование происходит от возврата либо a, либо b напрямую.) 14 май. 102010-05-14 06:57:48


51

Использование 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()]); 
} 
+10

Просто, но неэффективно, поскольку он создает массив для ArrayList, а затем генерирует другой метод toArray. Но все еще актуально, так как его просто читать. 10 мар. 142014-03-10 12:16:56


2

Если вы хотите работать с ArrayLists в растворе, вы можете попробовать это:

public final String [] f(final String [] first, final String [] second) { 
    // Assuming non-null for brevity. 
    final ArrayList<String> resultList = new ArrayList<String>(Arrays.asList(first)); 
    resultList.addAll(new ArrayList<String>(Arrays.asList(second))); 
    return resultList.toArray(new String [resultList.size()]); 
} 

0

Я тестировал ниже код и работал нормально

Также я использую библиотеку: org.apache.commons.lang.ArrayUtils

public void testConcatArrayString(){ 
    String[] a = null; 
    String[] b = null; 
    String[] c = null; 
    a = new String[] {"1","2","3","4","5"}; 
    b = new String[] {"A","B","C","D","E"}; 

    c = (String[]) ArrayUtils.addAll(a, b); 
    if(c!=null){ 
     for(int i=0; i<c.length; i++){ 
      System.out.println("c[" + (i+1) + "] = " + c[i]); 
     } 
    } 
} 

С уважением


4

Это работает, но вам необходимо вставить свою собственную проверку ошибок.

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

Это, вероятно, не самый эффективный, но он не опирается ни на что, кроме собственного API Java.

+1

+1. Было бы лучше заменить второй цикл 'for' следующим:' for (int j = 0; j <arr2.length; j ++) {arrBoth [arr1.length + j] = arr2 [j];} ' 28 окт. 102010-10-28 21:23:18


428

Возможно создать полностью универсальную версию, которую можно даже расширить, чтобы объединить любое количество массивов. Эта версия требует Java 6, так как они используют Arrays.copyOf()

Обе версии избежать создания каких-либо промежуточные List объектов и использовать System.arraycopy(), чтобы гарантировать, что копирование больших массивов как можно быстрее.

Для двух массивов это выглядит следующим образом:

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

А для произвольного числа массивов (> = 1) это выглядит следующим образом:

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: для массивов с примитивным типом вам нужно сделать перегруз для каждого типа: просто скопируйте код и замените каждый 'T' байтом (и потеряете' <T> '). 01 июн. 112011-06-01 06:01:58

  0

вы можете рассказать мне, как использовать <T> тип оператора в моем классе? 27 июн. 112011-06-27 02:22:04

+5

Я бы добавил это к началу, только чтобы быть оборонительным.if (первый == null) { если (второй == null) { возвращение null; } return second; } if (second == null) { возвращение сначала; } 22 сен. 112011-09-22 04:18:02

+4

@djBo: как насчет: 'ByteBuffer buffer = ByteBuffer.allocate (array1.length + array2.length); buffer.put (массив1); buffer.put (массив2); return buffer.array(); ' 02 дек. 112011-12-02 15:29:30

+12

В этом подходе есть ошибка, которая становится очевидной, если вы вызываете эти функции с массивами разных типов компонентов, например' concat (ai, ad) ', где' ai' является 'Integer [] 'и' ad' - 'Double []'. (В этом случае параметр типа '<T>' разрешен компилятором '<? Extends Number>'.) Массив, созданный 'Arrays.copyOf', будет иметь тип компонента первого массива, то есть' Integer' в этот пример. Когда функция собирается скопировать второй массив, будет выведено 'ArrayStoreException'. Решение состоит в том, чтобы иметь дополнительный параметр 'Class <T> type'. 25 июл. 132013-07-25 17:16:11

  0

@SamGoldberg, который работает только для 'byte []'. 26 июн. 142014-06-26 03:22:17

  0

@BrettOkken: да - вы правы. Я не знаю, почему я это предложил ... (вероятно, потому, что я только что написал код для объединения массивов байтов ...) 27 июн. 142014-06-27 16:09:34


2

простой, но неэффективный, способ чтобы сделать это (генерики не включены):

ArrayList baseArray = new ArrayList(Arrays.asList(array1)); 
baseArray.addAll(Arrays.asList(array2)); 
String concatenated[] = (String []) baseArray.toArray(new String[baseArray.size()]); 

4

простая вариация позволяет присоединение более одного массива:

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

Тип независимая вариация (ОБНОВЛЕНО - благодаря Залпу для инстанцирования T):

@SuppressWarnings("unchecked") 
public static <T> T[] join(T[]...arrays) { 

    final List<T> output = new ArrayList<T>(); 

    for(T[] array : arrays) { 
     output.addAll(Arrays.asList(array)); 
    } 

    return output.toArray((T[])Array.newInstance(
     arrays[0].getClass().getComponentType(), output.size())); 
} 
  0

T [] return type? 18 июн. 092009-06-18 14:52:10

  0

Мне все еще нравится решение Йоахима Зауера. 18 июн. 092009-06-18 14:56:23

  0

Я все еще на Java 5, поэтому не могу использовать Arrays.copyOf(), как делает Joachim. 18 июн. 092009-06-18 17:04:22


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

1

Еще один основанные на предложении SilverTab, но сделана для поддержки й числа аргументов и не требует Java 6. Он также не является общим, но я уверен, что он может быть общим.

private byte[] concat(byte[]... args) 
{ 
    int fulllength = 0; 
    for (byte[] arrItem : args) 
    { 
     fulllength += arrItem.length; 
    } 
    byte[] retArray = new byte[fulllength]; 
    int start = 0; 
    for (byte[] arrItem : args) 
    { 
     System.arraycopy(arrItem, 0, retArray, start, arrItem.length); 
     start += arrItem.length; 
    } 
    return retArray; 
} 

159

Или с любимым Guava:

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

Кроме того, существуют версии для примитивных массивов:

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

Насколько я люблю Guava, метод от Apache Commons лучше справляется с nullables. 01 ноя. 132013-11-01 19:19:54

+5

Хотя хорошо использовать библиотеки, к сожалению, проблема была отвлечена. Поэтому основное решение остается неуловимым. 09 апр. 142014-04-09 00:15:45

+35

В чем проблема с абстракцией? Не знаю, в чем дело с переосмыслением колеса здесь, если вы хотите узнать проблему, проверить источник или прочитать его. Профессиональный код должен использовать библиотеки высокого уровня, гораздо лучше, если он разработан внутри Google! 15 июл. 142014-07-15 20:11:00

  0

@RaviWallau Не могли бы вы ссылаться на класс, который это делает? 12 янв. 182018-01-12 14:48:48

+1

@ SébastienTromp Это лучшее решение для этого вопроса - ArrayUtils. 13 янв. 182018-01-13 04:45:13


1
Object[] obj = {"hi","there"}; 
Object[] obj2 ={"im","fine","what abt u"}; 
Object[] obj3 = new Object[obj.length+obj2.length]; 

for(int i =0;i<obj3.length;i++) 
    obj3[i] = (i<obj.length)?obj[i]:obj2[i-obj.length]; 

4

Вот мой немного улучшенная версия concatAll Йоахима Зауэра. Он может работать на Java 5 или 6, используя System.arraycopy Java 6, если он доступен во время выполнения. Этот метод (IMHO) идеально подходит для Android, поскольку он работает на Android < 9 (у которого нет System.arraycopy), но, если это возможно, будет использовать более быстрый метод.

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

Хорошая общая идея, но для тех, кто реализует: я бы предпочел варианты copyOf и non-copyOf, чем тот, который делает это как отражение. 12 сен. 112011-09-12 14:36:10


1

Самый простой способ я смог найти следующим образом:

 

List allFiltersList = Arrays.asList(regularFilters); 
allFiltersList.addAll(Arrays.asList(preFiltersArray)); 
Filter[] mergedFilterArray = (Filter[]) allFiltersList.toArray(); 
 
  0

Легко да. Но преобразование в список и из него не очень впечатляет. 04 июл. 112011-07-04 12:10:06


5

Это переделанный функция для массива строк:

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

2
Import java.util.*; 

String array1[] = {"bla","bla"}; 
String array2[] = {"bla","bla"}; 

ArrayList<String> tempArray = new ArrayList<String>(Arrays.asList(array1)); 
tempArray.addAll(Arrays.asList(array2)); 
String array3[] = films.toArray(new String[1]); // size will be overwritten if needed 

Вы можете заменить строку по Тип/класс по вашему выбору

Я уверен, что это можно сделать короче и лучше, но это работает, и им, чтобы ленивы, чтобы разобраться дальше ...


1

Вы можете попробовать это

public static Object[] addTwoArray(Object[] objArr1, Object[] objArr2){ 
    int arr1Length = objArr1!=null && objArr1.length>0?objArr1.length:0; 
    int arr2Length = objArr2!=null && objArr2.length>0?objArr2.length:0; 
    Object[] resutlentArray = new Object[arr1Length+arr2Length]; 
    for(int i=0,j=0;i<resutlentArray.length;i++){ 
     if(i+1<=arr1Length){ 
      resutlentArray[i]=objArr1[i]; 
     }else{ 
      resutlentArray[i]=objArr2[j]; 
      j++; 
     } 
    } 

    return resutlentArray; 
} 

U можно ввести отдать свой массив! !!


33

Раствор 100% старый Java и безSystem.arraycopy (не доступен в GWT клиента, например):

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

переработал мой файл [], но это то же самое. Спасибо за ваше решение. 07 сен. 122012-09-07 10:49:59

+2

Возможно, это довольно неэффективно. 11 апр. 152015-04-11 20:34:01

  0

Возможно, вы захотите добавить проверки «null». И, возможно, установите некоторые из ваших переменных в 'final'. 24 сен. 152015-09-24 14:31:33


5

Как насчет просто

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

И вобще Array.concat(arr1, arr2). Пока arr1 и arr2 имеют тот же тип, это даст вам другой массив того же типа, содержащий оба массива.

  0

По соображениям производительности я бы предварительно вычислил конечный размер ArrayList, потому что ArrayList по определению выделяет новый массив и копирует его элементы каждый раз, когда текущий массив заполнен. В противном случае я бы пошел прямо на LinkedList, который не страдает такой проблемой 20 авг. 152015-08-20 08:07:44


7

Здесь возможная реализация в рабочем коде решения псевдокода, написанном silvertab.

Спасибо 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; 
    } 
} 

Следующий следующий интерфейс строителя.

Примечание: Строитель необходимо потому, что в Java не представляется возможным сделать

new T[size]

вследствие общего типа стирания:

public interface ArrayBuilderI<T> { 

    public T[] build(int size); 
} 

Вот конкретный строитель, реализующий интерфейс, строительство a Integer:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> { 

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

И, наконец, приложение/тест:

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

0

В Haskell вы можете сделать что-то подобное [a, b, c] ++ [d, e] получить [a, b, c, d, e]. Это списки Haskell, объединенные, но было бы очень приятно видеть аналогичный оператор в Java для массивов. Разве вы так не думаете? Это изящно, просто, универсально, и это не так сложно реализовать.

Если вы хотите, я предлагаю вам взглянуть на работу Александра Христова в его Hacking the OpenJDK compiler. Он объясняет, как изменить источник javac для создания нового оператора. Его пример состоит в определении оператора «**», где i ** j = Math.pow(i, j). Можно взять этот пример для реализации оператора, который объединяет два массива одного типа.

Как только вы это сделаете, вы привязаны к своему настроенному javac для компиляции кода, но сгенерированный байт-код будет понят любой JVM.

Конечно, вы можете реализовать свой собственный метод конкатенации массива на вашем исходном уровне, есть много примеров того, как это сделать в других ответах!

Есть так много полезных операторов, которые могут быть добавлены, этот был бы одним из них.

  0

WOW nice! почему бы не изменить компилятор для реализации синтаксиса Java. :) смелый шаг! 19 окт. 152015-10-19 13:36:14


1

Посмотрите на это элегантное решение (если вам нужен другой тип, чем полукокса, изменить его):

private static void concatArrays(char[] destination, char[]... sources) { 
    int currPos = 0; 
    for (char[] source : sources) { 
     int length = source.length; 
     System.arraycopy(source, 0, destination, currPos, length); 
     currPos += length; 
    } 
} 

Вы можете сцепить каждый счетчик массивов.

  0

Добро пожаловать в stackoverflow. Поскольку этот вопрос довольно старый, и System.arraycopy был полностью обсужден, лучше избегать воскрешения старых потоков, если только ответ не вносит существенный вклад в поток. 07 апр. 122012-04-07 19:59:23

  0

Это не конкатенация, а копирование. У места назначения должно быть достаточно места для размещения всех источников или приведенный выше код вызовет исключение ArrayIndexOutOfBoundsException. 12 апр. 152015-04-12 22:01:00


2

я обнаружил, что приходилось иметь дело со случаем, когда массивы могут быть нулевой ...

private double[] concat (double[]a,double[]b){ 
    if (a == null) return b; 
    if (b == null) return a; 
    double[] r = new double[a.length+b.length]; 
    System.arraycopy(a, 0, r, 0, a.length); 
    System.arraycopy(b, 0, r, a.length, b.length); 
    return r; 

} 
private double[] copyRest (double[]a, int start){ 
    if (a == null) return null; 
    if (start > a.length)return null; 
    double[]r = new double[a.length-start]; 
    System.arraycopy(a,start,r,0,a.length-start); 
    return r; 
} 

11

Пожалуйста, простите меня за добавление еще одну версию этого уже длинный список. Я посмотрел на каждый ответ и решил, что мне действительно нужна версия с одним параметром в подписи. Я также добавил некоторые аргументы, чтобы извлечь выгоду из раннего отказа с разумной информацией в случае неожиданного ввода.

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

Я бы суммировал длину в том же цикле, где вы делаете свою нулевую проверку, но это действительно хорошее резюме других ответов здесь. Я считаю, что он даже обрабатывает внутренние типы, такие как «int», не меняя их на объекты Integer, которые на самом деле являются единственной причиной для решения этих задач как массивов, а не просто для изменения всех в ArrayLists. Также ваш метод может принимать 2 массива и параметр (...), чтобы вызывающий абонент знал, что ему нужно передать по крайней мере два массива, прежде чем он запустит его, и увидит ошибку, но это усложняет код цикла .... 15 авг. 172017-08-15 16:34:01


6

Wow! множество сложных ответов здесь, включая некоторые простые, которые зависят от внешних зависимостей. как насчет этого:

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

Простые и за работой. 29 дек. 142014-12-29 22:27:45

  0

..Но неэффективно и медленно. 11 апр. 152015-04-11 20:36:24


4

Другой способ подумать над вопросом.Чтобы объединить два или более массивов, нужно сделать это, чтобы перечислить все элементы каждого массива, а затем построить новый массив. Это звучит как создать List<T>, а затем называет toArray. В некоторых других ответах используется ArrayList, и все в порядке. Но как насчет внедрения наших собственных? Это не сложно:

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

Я считаю, что выше эквивалентно решениями, которые используют System.arraycopy. Однако я думаю, что у этого есть своя красота.


3
String [] both = new ArrayList<String>(){{addAll(Arrays.asList(first)); addAll(Arrays.asList(second));}}.toArray(new String[0]); 
+2

Tricky, он компилируется, только если 'first' и' second' являются окончательными 21 июн. 132013-06-21 13:20:58

+1

True. Я думал, что стоит добавить однострочный без внешней библиотеки. 21 июн. 132013-06-21 13:59:32

+1

ArrayList для конкатенации * и * Инициализация Double-Brace. 04 мар. 152015-03-04 17:34:50


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

both.toArray(new String[0]); 
+2

Ответ велик, но крошечный бит сломан. Чтобы сделать его идеальным, вы должны перейти к массиву toArray(), который вам нужен. В приведенном выше примере код должен быть: both.toArray (new String [0]) См .: http://stackoverflow.com/questions/4042434/converting-arrayliststring-to-string-in-java 15 фев. 172017-02-15 20:12:10

  0

Не знаю почему этот ответ не оценен выше ... хотя ему, похоже, нужно изменение, предложенное @RonenRabinovici 02 дек. 172017-12-02 11:14:34

+1

Или лучше, без ненужного выделения массива нулевой длины: 'both.toArray (new String [both.size()]) ';) 10 янв. 182018-01-10 16:42:24


0

Если сделать трюк. Это предполагает, что String [] первый и String [] второй

List<String> myList = new ArrayList<String>(Arrays.asList(first)); 
myList.addAll(new ArrayList<String>(Arrays.asList(second))); 
String[] both = myList.toArray(new String[myList.size()]); 
  0

' myList.addAll (новый ArrayList <String> (Arrays.asList (второй))); 'может быть упрощен до' myList.addAll (Arrays.asList (второй)) ' 24 май. 172017-05-24 14:07:41


0

Это один работает только с междунар но идея является общим

public static int[] junta(int[] v, int[] w) { 

int[] junta = new int[v.length + w.length]; 

for (int i = 0; i < v.length; i++) {    
    junta[i] = v[i]; 
} 

for (int j = v.length; j < junta.length; j++) { 
    junta[j] = w[j - v.length]; 
} 

300

Однострочник в Java 8:

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

или:

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

Насколько это эффективно? 02 окт. 152015-10-02 01:34:34

+5

Стоит прочитать: https://jaxenter.com/java-performance-tutorial-how-fast-are-the-java-8-streams-118830.html tl; dr - потоки могут быть выполнены или нет, это зависит от того, что вы делаете с ними и с ограничениями проблемы (не всегда ли это ответ? lol) 25 фев. 162016-02-25 17:29:03

  0

Да, это рискованное решение с точки зрения производительности. Это может быть быстро, но я бы не поставил на него свою производительность;) 07 апр. 162016-04-07 23:21:43

+3

Кроме того, если * a * или * b * являются массивами примитивных типов, их потоки должны быть '.boxed()', поэтому они типа 'Stream', а не, например, 'IntStream', который нельзя передать в качестве параметра в' Stream.concat'. 16 июл. 162016-07-16 09:59:48

+6

@Wow Hardwick-Smith: нет, вам нужно только выбрать подходящий класс потока, например. если 'a' и' b' являются 'int []', используйте 'int [] both = IntStream.concat (Arrays.stream (a), Arrays.stream (b)). toArray();' 13 июн. 172017-06-13 12:28:21

+1

@Supuhstar: Вероятно, это не так быстро, как 'System.arrayCopy'. Но не особенно медленным. Вероятно, вам придется делать это * очень * много раз с * огромными * массивами в * действительно * чувствительных к производительности контекстах для разницы во времени выполнения. 23 дек. 172017-12-23 15:43:00


1

Я думаю, что лучшие soluti на дженериков будет:

/* This for non primitive types */ 
public static <T> T[] concatenate (T[]... elements) { 

    T[] C = null; 
    for (T[] element: elements) { 
     if (element==null) continue; 
     if (C==null) C = (T[]) Array.newInstance(element.getClass().getComponentType(), element.length); 
     else C = resizeArray(C, C.length+element.length); 

     System.arraycopy(element, 0, C, C.length-element.length, element.length); 
    } 

    return C; 
} 

/** 
* as far as i know, primitive types do not accept generics 
* http://stackoverflow.com/questions/2721546/why-dont-java-generics-support-primitive-types 
* for primitive types we could do something like this: 
* */ 
public static int[] concatenate (int[]... elements){ 
    int[] C = null; 
    for (int[] element: elements) { 
     if (element==null) continue; 
     if (C==null) C = new int[element.length]; 
     else C = resizeArray(C, C.length+element.length); 

     System.arraycopy(element, 0, C, C.length-element.length, element.length); 
    } 
    return C; 
} 

private static <T> T resizeArray (T array, int newSize) { 
    int oldSize = 
      java.lang.reflect.Array.getLength(array); 
    Class elementType = 
      array.getClass().getComponentType(); 
    Object newArray = 
      java.lang.reflect.Array.newInstance(
        elementType, newSize); 
    int preserveLength = Math.min(oldSize, newSize); 
    if (preserveLength > 0) 
     System.arraycopy(array, 0, 
       newArray, 0, preserveLength); 
    return (T) newArray; 
} 

4

Как насчет:

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

1
public int[] mergeArrays(int [] a, int [] b) { 
    int [] merged = new int[a.length + b.length]; 
    int i = 0, k = 0, l = a.length; 
    int j = a.length > b.length ? a.length : b.length; 
    while(i < j) { 
     if(k < a.length) { 
      merged[k] = a[k]; 
      k++; 
     } 
     if((l - a.length) < b.length) { 
      merged[l] = b[l - a.length]; 
      l++; 
     } 
     i++; 
    } 
    return merged; 
} 

10

Вы могли бы попытаться превратить его в Arraylist и использовать метод addAll затем преобразовать обратно в массив.

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

Хорошее решение - было бы лучше, если бы код был реорганизован, чтобы избежать массивов вообще в пользу ArrayLists, но это вне контроля «Ответ» и до вопросителя. 15 авг. 172017-08-15 16:29:17


16

Другой способ с использованием Java8 потока

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

2
public static String[] toArray(String[]... object){ 
    List<String> list=new ArrayList<>(); 
    for (String[] i : object) { 
     list.addAll(Arrays.asList(i)); 
    } 
    return list.toArray(new String[list.size()]); 
} 

1
Object[] mixArray(String[] a, String[] b) 
String[] s1 = a; 
String[] s2 = b; 
Object[] result; 
List<String> input = new ArrayList<String>(); 
for (int i = 0; i < s1.length; i++) 
{ 
    input.add(s1[i]); 
} 
for (int i = 0; i < s2.length; i++) 
{ 
    input.add(s2[i]); 
} 
result = input.toArray(); 
return result; 

1

Каждый ответ копирование данных и создание нового массива. Это не является строго необходимым и определенно НЕ является тем, что вы хотите сделать, если ваши массивы достаточно велики. Создатели Java уже знали, что массивные копии являются расточительными, и именно поэтому они предоставили нам System.arrayCopy(), чтобы делать эти внешние Java, когда мы должны.

Вместо того, чтобы копировать ваши данные, подумайте о том, чтобы оставить его на месте и извлечь из него, где он лежит. Копирование местоположений данных только потому, что программист хотел бы их организовать, не всегда разумно.

// I have arrayA and arrayB; would like to treat them as concatenated 
// but leave my damn bytes where they are! 
Object accessElement (int index) { 
    if (index < 0) throw new ArrayIndexOutOfBoundsException(...); 
    // is reading from the head part? 
    if (index < arrayA.length) 
      return arrayA[ index ]; 
    // is reading from the tail part? 
    if (index < (arrayA.length + arrayB.length)) 
      return arrayB[ index - arrayA.length ]; 
    throw new ArrayIndexOutOfBoundsException(...); // index too large 
} 

1

Здесь код AbacusUtil.

String[] a = {"a", "b", "c"}; 
String[] b = {"1", "2", "3"}; 
String[] c = N.concat(a, b); // c = ["a", "b", "c", "1", "2", "3"] 

// N.concat(...) is null-safety. 
a = null; 
c = N.concat(a, b); // c = ["1", "2", "3"] 

1
void f(String[] first, String[] second) { 
    String[] both = new String[first.length+second.length]; 
    for(int i=0;i<first.length;i++) 
     both[i] = first[i]; 
    for(int i=0;i<second.length;i++) 
     both[first.length + i] = second[i]; 
} 

Это один работает без знания каких-либо других классов/библиотек и т.д. Это работает для любого типа данных. Просто замените String на что-нибудь наподобие int, double или char. Он работает довольно эффективно.


11

Если вы используете этот способ, вам не нужно импортировать какой-либо сторонний класс.

Если вы хотите конкатенации String

Пример кода для concate два массива строк

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

Если вы хотите конкатенации Int

Пример кода для concate два целочисленных массива

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

Вот Основной метод

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

     } 
    } 

Мы можем использовать этот путь также.


0

Еще один ответ для любителей алгоритма:

public static String[] mergeArrays(String[] array1, String[] array2) { 
    int totalSize = array1.length + array2.length; // Get total size 
    String[] merged = new String[totalSize]; // Create new array 
    // Loop over the total size 
    for (int i = 0; i < totalSize; i++) { 
     if (i < array1.length) // If the current position is less than the length of the first array, take value from first array 
      merged[i] = array1[i]; // Position in first array is the current position 

     else // If current position is equal or greater than the first array, take value from second array. 
      merged[i] = array2[i - array1.length]; // Position in second array is current position minus length of first array. 
    } 

    return merged; 

Использование:

String[] array1str = new String[]{"a", "b", "c", "d"}; 
String[] array2str = new String[]{"e", "f", "g", "h", "i"}; 
String[] listTotalstr = mergeArrays(array1str, array2str); 
System.out.println(Arrays.toString(listTotalstr)); 

Результат:

[a, b, c, d, e, f, g, h, i] 

0

Вы можете попробовать этот метод, который сцепляет несколько массивов:

public static <T> T[] concatMultipleArrays(T[]... arrays) 
{ 
    int length = 0; 
    for (T[] array : arrays) 
    { 
     length += array.length; 
    } 
    T[] result = (T[]) Array.newInstance(arrays.getClass().getComponentType(), length) ; 

    length = 0; 
    for (int i = 0; i < arrays.length; i++) 
    { 
     System.arraycopy(arrays[i], 0, result, length, arrays[i].length); 
     length += arrays[i].length; 
    } 

    return result; 
}