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

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

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

Какой самый простой способ сделать это?

1194
задан 17 сент. '08 в 9:14
источник поделиться
58 ответов
  • 1
  • 2

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

код:

String[] both = (String[])ArrayUtils.addAll(first, second);
955
ответ дан 17 сент. '08 в 9:34
источник

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

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 }));
734
ответ дан 17 сент. '08 в 9:20
источник

Можно написать полностью общую версию, которая может быть даже расширена, чтобы объединить любое количество массивов. Для этих версий требуется 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;
}
446
ответ дан 24 апр. '09 в 10:28
источник

Однострочный в 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);
362
ответ дан 21 апр. '14 в 2:52
источник

Или с любимым 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)
173
ответ дан 09 марта '11 в 18:19
источник

Использование 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()]);
}
56
ответ дан 18 сент. '08 в 23:59
источник

Решение 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;
}
40
ответ дан 11 окт. '11 в 13:54
источник

Недавно я столкнулся с проблемами с чрезмерным вращением памяти. Если a и/или b, как известно, обычно пусты, вот еще одна адаптация кода 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!)

31
ответ дан 17 сент. '08 в 19:52
источник

Вы можете добавить два массива в две строки кода.

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

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

Вам следует избегать решений, включающих ArrayLists, потоки и т.д., Так как они должны будут выделять временную память без какой-либо полезной цели.

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

30
ответ дан 11 апр. '18 в 13:17
источник

Функциональная библиотека Java имеет класс оболочки-массива, который оснащает массивы удобными методами, такими как конкатенация.

import static fj.data.Array.array;

... и затем

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

Чтобы вернуть освобожденный массив, вызовите

String[] s = both.array();
27
ответ дан 17 сент. '08 в 9:52
источник
ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));

both.toArray(new String[0]);
26
ответ дан 21 авг. '13 в 9:27
источник

Здесь адаптация решения 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 для решения Java 6. Это не только устраняет предупреждение; он также короче, эффективнее и легче читать!

17
ответ дан 17 сент. '08 в 19:47
источник

Другой способ использования Java8 с помощью 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); 
  }
16
ответ дан 10 февр. '16 в 15:48
источник

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

Если вы хотите объединить String

Пример кода для concate двух 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;
    }

Если вы хотите объединить 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));

        }
    }  

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

12
ответ дан 13 февр. '17 в 13:17
источник

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

@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;
}
11
ответ дан 13 июля '12 в 15:08
источник

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

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();
10
ответ дан 14 нояб. '15 в 21:45
источник

Здесь возможная реализация в рабочем коде решения псевдокода, написанного 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);
}

Здесь конкретный строитель, реализующий интерфейс, построив массив Integer:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

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

И, наконец, приложение /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
ответ дан 04 янв. '12 в 17:35
источник

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

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

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

6
ответ дан 24 апр. '09 в 10:12
источник

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

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]);
6
ответ дан 28 окт. '12 в 23:23
источник

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

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 имеют один и тот же тип, это даст вам другой массив того же типа, содержащий оба массива.

5
ответ дан 12 окт. '11 в 3:15
источник

Это преобразованная функция для массива 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;
}
5
ответ дан 11 июня '11 в 22:59
источник

Как насчет:

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
ответ дан 12 февр. '15 в 2:35
источник

Простая вариация, позволяющая объединить несколько массивов:

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()]);
}
4
ответ дан 18 июня '09 в 15:07
источник

Еще один способ задуматься над вопросом. Чтобы объединить два или более массивов, нужно сделать это, чтобы перечислить все элементы каждого массива, а затем построить новый массив. Это похоже на создание 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. Однако я думаю, что у этого есть своя красота.

4
ответ дан 27 февр. '13 в 6:03
источник

Вот моя немного улучшенная версия Joachim Sauer concatAll. Он может работать на Java 5 или 6, используя Java 6 System.arraycopy, если он доступен во время выполнения. Этот метод (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;
  }
4
ответ дан 09 июня '11 в 18:48
источник
String [] both = new ArrayList<String>(){{addAll(Arrays.asList(first)); addAll(Arrays.asList(second));}}.toArray(new String[0]);
3
ответ дан 21 июня '13 в 15:59
источник

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

ArrayList baseArray = new ArrayList(Arrays.asList(array1));
baseArray.addAll(Arrays.asList(array2));
String concatenated[] = (String []) baseArray.toArray(new String[baseArray.size()]);
3
ответ дан 24 апр. '09 в 18:52
источник

Независимость от типа (ОБНОВЛЕНО - благодаря Volley для создания экземпляра 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()));
}
3
ответ дан 18 июня '09 в 15:13
источник

Использование только собственного API 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]);
}

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

3
ответ дан 17 сент. '08 в 11:02
источник
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;
}
3
ответ дан 29 дек. '11 в 10:29
источник
  • 1
  • 2

Другие вопросы по меткам или Задайте вопрос