15

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

12

Я столкнулся с проблемой в Java: мне нужно объединить два массива типа String. Вот что у меня есть:

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

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

5 ответ(ов)

7

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

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

Вы можете объединить два массива всего в две строки кода:

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

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

Избегайте решений, связанных с ArrayList, потоками и т.д., так как они потребуют выделения временной памяти без особой необходимости.

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

0

Ваш код на Java объединяет два массива строк и возвращает новый массив, содержащий все элементы из обоих массивов. Вот перевод и объяснение вашего подхода:

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

В этом методе f:

  1. Создается новый список both с начальной емкостью, равной сумме длин обоих массивов first и second.
  2. Метод Collections.addAll используется для добавления всех элементов из первого массива first в список both.
  3. Затем снова вызывается Collections.addAll для добавления всех элементов из второго массива second.
  4. В конце, метод toArray преобразует список в массив строк, который и возвращается.

Этот подход является эффективным и простым способом объединения массивов строк. Если у вас есть дополнительные вопросы или вам нужно более подробно разобрать какие-то аспекты, пожалуйста, дайте знать!

0

Вам нужно реализовать метод для конкатенации массивов строк в Java, не используя System.arraycopy и придерживаясь "старого" подхода. Вот пример функции, которая выполняет эту задачу:

static String[] concat(String[]... arrays) {
    int totalLength = 0;
    // Сначала определяем общую длину всех массивов
    for (String[] array : arrays) {
        totalLength += array.length;
    }
    
    // Создаём новый массив с общей длиной
    String[] result = new String[totalLength];
    int position = 0;
    
    // Заполняем новый массив элементами из входящих массивов
    for (String[] array : arrays) {
        for (int i = 0; i < array.length; i++) {
            result[position] = array[i];
            position++;
        }
    }
    
    return result;
}

Этот метод принимает переменное количество массивов строк и объединяет их в один. Первоначально происходит подсчёт общей длины всех массивов, затем создается новый массив этой длины. В конце мы заполняем новый массив элементами из всех входящих массивов, перебирая их через обычные циклы.

Такой подход полностью совместим со старыми версиями Java и работает даже в средах, где System.arraycopy недоступен, как, например, в GWT клиенте.

0

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

private static <T> T[] concatOrReturnSame(T[] a, T[] b) {
    final int alen = a.length;
    final int blen = b.length;
    if (alen == 0) {
        return b;
    }
    if (blen == 0) {
        return a;
    }
    final T[] result = (T[]) java.lang.reflect.Array.
            newInstance(a.getClass().getComponentType(), alen + blen);
    System.arraycopy(a, 0, result, 0, alen);
    System.arraycopy(b, 0, result, alen, blen);
    return result;
}

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

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