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

1135

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

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

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

  • 2
    Bytes.concat из Гуавы
  • 1
    Здесь я вижу много ответов, но вопрос так сформулирован («самый простой способ»?), Что не позволяет указать лучший ответ ...
Показать ещё 4 комментария
Теги:
arrays
concatenation
add

58 ответов

908

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

код:

String[] both = (String[])ArrayUtils.addAll(first, second);
  • 358
    Я не знаю, это своего рода обман. Я думаю, что большинство людей, вероятно, не захотят дополнительную зависимость для этого одного метода.
  • 152
    Как это «обманывать», если он отвечает на вопрос? Конечно, наличие дополнительной зависимости, вероятно, излишне для этой конкретной ситуации, но не вызывает никакого вреда, когда мы говорим, что она существует, тем более, что в Apache Commons так много отличных функциональных возможностей.
Показать ещё 11 комментариев
698

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

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, недоступны.
  • 3
    Следующая строка будет разбивать общую часть: concatenate (new String [] {"1"}, new Object [] {new Object ()})
Показать ещё 1 комментарий
446

Можно написать полностью общую версию, которая может быть даже расширена, чтобы объединить любое количество массивов. Для этих версий требуется 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 byte (и потеряйте <T> ).
  • 0
    Можете ли вы сказать мне, как использовать тип оператора <T> в моем классе?
Показать ещё 5 комментариев
380

Однострочный в 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);
  • 23
    Насколько это эффективно?
  • 7
    Стоит прочитать: jaxenter.com/… tl; dr - потоки могут быть эффективными или нет, это зависит от того, что вы делаете с ними, и ограничений проблемы (разве это не всегда ответ? Lol)
Показать ещё 8 комментариев
181

Или с любимым 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
    Как бы я ни любил Гуаву, метод Apache Commons лучше справляется с обнуляемыми значениями.
  • 7
    Хотя использовать библиотеки полезно, к сожалению, проблема была устранена. Поэтому основное решение остается неуловимым.
Показать ещё 3 комментария
54

Использование 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()]);
}
  • 12
    Просто, но неэффективно, поскольку он создает массив для ArrayList, а затем генерирует другой для метода toArray. Но все же актуально, так как его легко читать.
  • 0
    применимо к строкам и объектам (по желанию вопроса), но нет метода addAll для основных типов (как целых)
Показать ещё 1 комментарий
40

Решение 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
    переработан мой для File [], но это то же самое. Спасибо за ваше решение
  • 5
    Вероятно, довольно неэффективно, хотя.
Показать ещё 4 комментария
31

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

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

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

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

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

31

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

  • 5
    это, однако, означает, что вы возвращаете один и тот же массив, и изменение значения в возвращенном массиве изменяет значение в той же позиции, что и возвращенный входной массив.
  • 0
    Да - см. Комментарий в конце моего поста относительно повторного использования массива. Затраты на обслуживание, налагаемые этим решением, в нашем конкретном случае стоили того, но в большинстве случаев, вероятно, следует использовать защитное копирование.
Показать ещё 4 комментария
27

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

import static fj.data.Array.array;

... и затем

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

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

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

both.toArray(new String[0]);
  • 3
    Ответ отличный, но немного сломанный. Чтобы сделать его идеальным, вы должны передать toArray () массив нужного вам типа. В приведенном выше примере код должен быть следующим: both.toArray (new String [0]). См .: stackoverflow.com/questions/4042434/…
  • 0
    Не знаю, почему этот ответ не оценен выше ... хотя, похоже, ему нужно изменение, предложенное @RonenRabinovici
Показать ещё 2 комментария
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 для решения Java 6. Это не только устраняет предупреждение; он также короче, эффективнее и легче читать!

  • 0
    Вы можете подавить предупреждение для этого метода, но кроме этого, вы ничего не можете сделать. Массивы и дженерики на самом деле не смешиваются.
  • 3
    Непроверенное предупреждение может быть устранено, если вы используете Arrays.copyOf (). Смотрите мой ответ для реализации.
Показать ещё 1 комментарий
16

Другой способ использования 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); 
  }
12

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

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

        }
    }  

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

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 массива и параметр (...), поэтому вызывающий объект знает, что ему нужно передать как минимум два массива, прежде чем он запустит его, и увидит ошибку, но это усложняет циклический код ....
10

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

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();
  • 0
    Хорошее решение - было бы лучше, если бы код был подвергнут рефакторингу, чтобы вообще избежать массивов в пользу ArrayLists, но это вне контроля «ответа» и зависит от спрашивающего.
  • 0
    Я считаю, что для работы требуется 4 дополнительных временных объекта.
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);
}

Здесь конкретный строитель, реализующий интерфейс, построив массив 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]);
   }
}
6

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

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
    Просто и работает.
  • 1
    ..Но неэффективно и медленно.
6

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

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.

  • 2
    +1. Лучше заменить второй цикл for : for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
  • 0
    Используйте String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length) чтобы пропустить первый цикл for . Экономит время, пропорциональное размеру arr1 .
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, который не страдает от такой проблемы
5

Это преобразованная функция для массива 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;
}
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()]);
}
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. Однако я думаю, что у этого есть своя красота.

4

Вот моя немного улучшенная версия 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;
  }
  • 1
    Хорошая общая идея, но для всех, кто реализует: я бы предпочел версии copyOf и non-copyOf, а не те, которые используют оба способа в качестве отражения.
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
String [] both = new ArrayList<String>(){{addAll(Arrays.asList(first)); addAll(Arrays.asList(second));}}.toArray(new String[0]);
  • 2
    Хитрый, он компилируется только если first и second являются окончательными
  • 1
    Правда. Я думал, что стоит добавить однострочник без внешней библиотеки.
Показать ещё 1 комментарий
3
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

Независимость от типа (ОБНОВЛЕНО - благодаря 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()));
}
  • 0
    T [] тип возвращаемого значения?
  • 0
    Мне все еще нравится решение Йоахима Зауэра.
Показать ещё 1 комментарий
3

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

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

Использование только собственного 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 [] (даже нулевые массивы).

  • 15
    Пришлось понизить это за все ненужное создание объекта List.
2

Общая статическая версия, в которой используется высокопроизводительная System.arraycopy, не требующая аннотации @SuppressWarnings:

public static <T> T[] arrayConcat(T[] a, T[] b) {
    T[] both = Arrays.copyOf(a, a.length + b.length);
    System.arraycopy(b, 0, both, a.length, b.length);
    return both;
}
2

Это должно быть однострочным.

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

Используя потоки Java 8+, вы можете написать следующую функцию:

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

Каждый ответ - копирование данных и создание нового массива. Это не является строго необходимым и определенно НЕ является тем, что вы хотите сделать, если ваши массивы достаточно велики. Создатели 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
}
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()]);
}
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;
}
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

Вы можете заменить String типом/классом по своему вкусу

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

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

В Java 8

public String[] concat(String[] arr1, String[] arr2){
    Stream<String> stream1 = Stream.of(arr1);
    Stream<String> stream2 = Stream.of(arr2);
    Stream<String> stream = Stream.concat(stream1, stream2);
    return Arrays.toString(stream.toArray(String[]::new));
}
  • 0
    Это то же самое, что и предыдущий ответ 10 февраля 16.
  • 0
    Я не видел, что спасибо, что сообщили мне
Показать ещё 2 комментария
1

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

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;
}
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
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
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;
}
  • 0
    Это очень запутанно, трудно понять, без документов и - с двумя операторами if в цикле - довольно неэффективно.
1

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

/* 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;
}
  • 0
    Это похоже на полезный код и ловит как объекты, так и базовые типы. Однако я бы не вызывал функцию resizeArray потому что массивы нельзя изменить в Java. Вот почему Arrays.copyOf делает то же самое, но с другим именем метода.
  • 0
    Не совсем, copyOf просто делает копию той же длины, если вы внимательно прочитаете код, вы поймете, что функция получает параметр newSize поэтому resizeArray делает именно это и возвращает массив с newSize размером.
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 может набирать ваш массив!!!

  • 0
    resutlentArray ? addTwoArray ? Трудно читать код и комментарии в стиле YouTube !!!
1

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


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

  • 1
    Легко да. Но преобразование в Список и из Списка звучит не очень эффективно.
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];
  • 0
    Пожалуйста, объясните свой код - вот почему
1

Еще один, основанный на предположении SilverTab, но сделан для поддержки x аргументов и не требует 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;
}
0

Вероятно, это единственный общий и безопасный для типов способ:

public class ArrayConcatenator<T> {
    private final IntFunction<T[]> generator;

    private ArrayConcatenator(IntFunction<T[]> generator) {
        this.generator = generator;
    }

    public static <T> ArrayConcatenator<T> concat(IntFunction<T[]> generator) {
        return new ArrayConcatenator<>(generator);
    }

    public T[] apply(T[] array1, T[] array2) {
        T[] array = generator.apply(array1.length + array2.length);
        System.arraycopy(array1, 0, array, 0, array1.length);
        System.arraycopy(array2, 0, array, array1.length, array2.length);
        return array;
    }
}

И использование довольно кратко:

Integer[] array1 = { 1, 2, 3 };
Double[] array2 = { 4.0, 5.0, 6.0 };
Number[] array = concat(Number[]::new).apply(array1, array2);

(требуется статический импорт)

Неверные типы массивов отклоняются:

concat(String[]::new).apply(array1, array2); // error
concat(Integer[]::new).apply(array1, array2); // error
0

Вы можете использовать коллекцию ArrayList для этого. его реализация очень проста для понимания, сначала вы должны хранить оба массива String, которые представлены в аргументах в ArrayList, а после этого просто конвертировать этот ArrayList в массив String с помощью метода toArray(), вот реализация:

public static void f(String[] first, String[] second) {
            ArrayList<String> list = new ArrayList<>();

            for(String s: first){
                list.add(s);
            }
            for(String s: second){
                list.add(s);
            }

            String[] both = list.toArray(new String[list.size()]);
            System.out.println(list.toString());

        }
0

Решение Non Java 8:

public static int[] combineArrays(int[] a, int[] b) {
        int[] c = new int[a.length + b.length];

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

        for (int j = 0, k = a.length; j < b.length; j++, k++) {
            c[k] = b[j];
        }

        return c;
    }
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
    Оператор if для каждой копии не является блестящей идеей, поскольку он будет иметь огромный успех.
  • 0
    @MaartenBodewes всегда приятно изучать новые подходы, ориентированные на производительность. Любые предложения по улучшению этого?
Показать ещё 1 комментарий
0
    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. Он работает достаточно эффективно.

  • 0
    Трата процессора и памяти. Смотрите ответ от @ Douglas-Held
0

Это работает только с int, но идея является общей

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

Должен сделать трюк. Сначала предполагается, что String [] и String [] second

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(new ArrayList<String>(Arrays.asList(second))); может быть упрощено до myList.addAll(Arrays.asList(second))
0

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

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 уже подробно обсуждался, лучше избегать воскрешения старых потоков, если ответ не внесет в поток что-то существенное.
  • 1
    Это не конкатенация, а копирование. В месте назначения уже должно быть достаточно места для размещения всех источников, или приведенный выше код вызовет исключение ArrayIndexOutOfBoundsException.
0

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

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

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

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


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

  • 0
    Вау круто! почему бы не изменить компилятор для реализации проблемы синтаксиса Java. :) смелый шаг!
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]);
        }
    }
}

Привет

Ещё вопросы

Сообщество Overcoder
Наверх
Меню