Мне нужно объединить два массива String в Java.
void f(String[] first, String[] second) {
String[] both = ???
}
Как это сделать проще всего?
Я вижу здесь много ответов, но вопрос сформулирован так («самый простой способ»?), Что не позволяет указать лучший ответ ...
Десятки ответов здесь - это копирование данных в новый массив, потому что это то, что было запрошено, но копирование данных, когда это не является строго необходимым, - плохая вещь, особенно в Java. Вместо этого отслеживайте индексы и используйте два массива, как если бы они были соединены. Я добавил решение, иллюстрирующее эту технику.
Самым простым является то, что вам, вероятно, в первую очередь не следует использовать массивы, вы должны использовать ArrayLists, а ваш вывод должен быть ArrayList. Как только вы сделали это своим предварительным условием, операция будет встроенной - first.addAll (second). Единственный случай, когда это не будет в значительной степени автоматическим, - это когда ваши массивы не являются объектными типами (int, long, double, ...), в этом случае внутренние массивы могут иметь большое преимущество перед ArrayLists, но для строк --мех
Тот факт, что на такой вопрос в настоящее время есть 50 разных ответов, заставляет меня задаться вопросом, почему в Java никогда не было простой конкатенации array1 + array2.
Вы можете сделать это отлично и очень эффективно в двух строчках стандартной Java (см. Мой ответ), так что не так уж много можно получить, имея единственный метод для этого. Все эти странные и чудесные решения - пустая трата времени.




Вот простой метод, который объединит два массива и вернет результат:
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 }));
Мне нравится это предложение, поскольку оно меньше зависит от последних версий Java. В своих проектах я часто застреваю, используя старые версии профилей Java или CLDC, где некоторые из средств, подобных упомянутым Антти, недоступны.
Следующая строка разорвет общую часть: concatenate (new String [] {"1"}, new Object [] {new Object ()})
было бы неплохо не использовать аннотацию @SuppressWarnings - я опубликую решение для этого ниже.
+1 для Array.newInstance(a.getClass().getComponentType(), aLen + bLen);. Удивительно, но я никогда раньше такого не видел. @beaudet Я думаю, что аннотация здесь хороша, учитывая, почему она подавляется.
ха, назовите меня пуристом, но я предпочитаю чистый код, который не требует подавления предупреждений, чтобы убрать предупреждения
Есть разница между семантическими предупреждениями и «Я использую необработанную память, как в C, поэтому отключите свою безопасность, поскольку я знаю, что делаю» «Я небезопасен» - это не подавление семантических предупреждений. Это «Я намеренно ухожу на более низкий уровень, так что хватит ныть». Почувствуйте удачу, ведь Swift 5 убрал глушители. Java, в отличие от Swift, по-прежнему предназначен для программистов, которые не боятся заниматься программированием самостоятельно.
Я нашел однострочное решение из старой доброй библиотеки Apache Commons Lang.ArrayUtils.addAll(T[], T...)
Код:
String[] both = ArrayUtils.addAll(first, second);
Как это "обман", если он отвечает на вопрос? Конечно, наличие дополнительной зависимости, вероятно, является излишним для этой конкретной ситуации, но не будет никакого вреда, если объявить, что она существует, тем более, что в Apache Commons так много отличных функциональных возможностей.
Я согласен, это не совсем ответ на вопрос. Библиотеки высокого уровня могут быть замечательными, но если вы хотите узнать эффективный способ сделать это, вам нужно взглянуть на код, который использует метод библиотеки. Кроме того, во многих ситуациях нельзя просто «на лету» использовать другую библиотеку в продукте.
Думаю, это хороший ответ. Решения POJO также были предоставлены, но если OP уже использует Apache Commons в своей программе (что вполне возможно, учитывая его популярность), он все еще может не знать об этом решении. Тогда он не стал бы «добавлять зависимость для этого единственного метода», а лучше использовал бы существующую библиотеку.
@ Outlaw Programmer, я думаю, что большинство людей предпочли бы использовать самый простой из возможных методов. Java уже достаточно многословна.
Я использую commons-lang-2.4.jar. В ArrayUtils нет универсальной версии addAll (). Поэтому мне пришлось явно преобразовать возвращаемый Object [] в String [].
вы могли бы дать ссылку на ответ, как и сделали, и вставить реализацию из источника. это решило бы указанные выше вопросы о "мошенничестве" в вашем ответе.
ОП попросил самый простой способ решить проблему. Это действительно самый простой способ, но только при условии, что библиотека уже присутствует, что не упоминается в вопросе. В противном случае на самом деле намного проще скопировать и вставить несколько строк кода, чем копировать только одну, а затем возиться с добавлением отдельной библиотеки в проект.
Если вы всегда беспокоитесь о том, чтобы не добавлять библиотеку для одного метода, новые библиотеки никогда не будут добавлены. Учитывая отличные утилиты, представленные в Apache Commons, я настоятельно рекомендую добавить их, когда возникнет самый первый вариант использования.
@Antti Sykäri, извините за вопрос, я новичок в Java, почему (String[]) используется в String[] both = (String[])ArrayUtils.addAll(first, second); без него, не будет ли он объединять 2 массива
использование Apache Commons никогда не следует называть «обманом», я сомневаюсь в здравом уме разработчиков, которые считают его ненужной зависимостью.
ArrayUtils можно скачать по адресу commons.apache.org/proper/commons-lang/download_lang.cgi
@OutlawProgrammer Я редко сомневаюсь в добавлении зависимости к моему приложению, если это упрощает код и означает, что мне нужно меньше поддерживать. Большинство людей не работают с такими ограничениями, которые заставляют беспокоиться о добавлении зависимости. (То есть, у них много места на диске, им не нужно самое быстрое во всем и т. д.)
Подобные решения помогают людям, работающим в одиночку над своими хобби-проектами, но не вносят никакого вклада, когда вы работаете над проектом компании или в основном над проектом, вам просто не следует добавлять новую зависимость для объединения двух массивов.
Одно сомнение, может ли он обрабатывать null, например, если null есть ответ, это пустая строка или пустая строка, если другая пуста?
Это не должен быть ответ номер один. Ответ с использованием внешней библиотеки для чего-то столь тривиального - излишний.
@JohnnyLim, как преобразовать Object [] в String [] при использовании ArrayUtils.addAll(Arr1, Arr2)? Мой Arr1 / Arr2 инициализирован как List<Object> obj = new ArrayList<>() с содержимым из double, string и т. д.
Библиотека Функциональная Java имеет класс-оболочку массива, который оснащает массивы удобными методами, такими как конкатенация.
import static fj.data.Array.array;
...а потом
Array<String> both = array(first).append(array(second));
Чтобы вернуть развернутый массив, вызовите
String[] s = both.array();
Использование только собственного 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 [] (даже с нулевыми массивами).
Пришлось проголосовать против этого за создание всего ненужного объекта List.
Вот адаптация решения 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;
}
ПРИМЕЧАНИЕ. См. Ответ Иоахима для решения Java 6. Это не только устраняет предупреждение; он также короче, эффективнее и легче читается!
Вы можете подавить предупреждение для этого метода, но кроме этого вы мало что можете сделать. Массивы и дженерики на самом деле несовместимы.
Непроверенное предупреждение можно устранить, если использовать Arrays.copyOf (). См. Мой ответ для реализации.
@SuppressWarnings ("не отмечено")
Я недавно боролся с проблемами чрезмерной ротации памяти. Если известно, что 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 и были в первую очередь сутью этой конкретной оптимизации. Я оставлю этот ответ здесь, но будьте осторожны!
это, однако, означает, что вы возвращаете тот же массив, и изменение значения в возвращаемом массиве изменяет значение в той же позиции возвращенного входного массива.
Да - см. Комментарий в конце моего сообщения о повторном использовании массива. Накладные расходы на обслуживание, связанные с этим решением, в нашем конкретном случае того стоили, но в большинстве случаев, вероятно, следует использовать защитное копирование.
Лоренцо / залп, не могли бы вы объяснить, какая часть кода вызывает повторное использование массива? Я думал, System.arraycopy копирует содержимое массива?
Вызывающий обычно ожидает, что вызов concat () вернет вновь выделенный массив. Однако, если a или b равно нулю, concat () вернет один из переданных ему массивов. Это повторное использование может быть неожиданным. (Да, arraycopy выполняет только копирование. Повторное использование происходит при прямом возврате a или b.)
Код должен быть как можно более понятным. Людям, читающим код, не нужно искать в JavaDoc вызываемой функции, чтобы узнать, что она выполняет одно действие для одного конкретного условия, а другое - для другого. Вкратце: как правило, вы не можете исправить подобные проблемы с дизайном с помощью комментария. Самым простым решением было бы просто исключить два оператора if.
@MaartenBodewes Я согласен. Этот метод использовался в очень конкретном месте для устранения очень конкретной проблемы, выявленной с помощью профилирования. Отредактирую комментарий о JavaDoc.
Попробуйте использовать это в char [] = {'a'}: /
Используя 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()]);
}
Просто, но неэффективно, поскольку он создает массив для ArrayList, а затем генерирует другой для метода toArray. Но все же актуально, так как это просто читать.
применимо для строк и объектов (как хочет вопрос), но нет метода addAll для первичных типов (как целые числа)
Как уточняется в Эта статья, использование both.toArray(new String[0]) будет быстрее, чем both.toArray(new String[both.size()]), даже если это противоречит нашей наивной интуиции. Вот почему так важно измерять фактическую производительность при оптимизации. Или просто используйте более простую конструкцию, когда преимущество более сложного варианта не может быть доказано.
Если вы хотите работать с 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()]);
}
Я тестировал код ниже и работал нормально
Также я использую библиотеку: 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]);
}
}
}
С Уважением
Это работает, но вам нужно вставить свою собственную проверку ошибок.
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. Второй шлейф for лучше заменить на for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}.
Используйте String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length), чтобы пропустить первый цикл for. Экономия времени пропорциональна размеру arr1.
Можно написать полностью общую версию, которую можно даже расширить для объединения любого количества массивов. Для этих версий требуется 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;
}
@djBO: для массивов с примитивными типами вам нужно будет сделать перегрузку для каждого типа: просто скопируйте код и замените каждый T на byte (и потеряйте <T>).
Подскажите, пожалуйста, как использовать тип оператора <T> в моем классе?
Я бы добавил это в начало, чтобы защитить себя. if (first == null) {if (second == null) {return null; } вернуть вторую; } если (второй == ноль) {вернуть первый; }
@djBo: что насчет: ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
В этом подходе есть ошибка, которая становится очевидной, если вы вызываете эти функции с массивами из разных типов компонентов, например concat(ai, ad), где ai - это Integer[], а ad - это Double[]. (В этом случае параметр типа <T> преобразуется компилятором в <? extends Number>.) Массив, созданный Arrays.copyOf, будет иметь компонентный тип первого массива, то есть Integer в этом примере. Когда функция собирается скопировать второй массив, будет выдан ArrayStoreException. Решение состоит в том, чтобы иметь дополнительный параметр Class<T> type.
@BrettOkken: да, вы правы. Я не знаю, почему я это предложил ... (возможно, потому, что я только что написал код для объединения байтовых массивов ...)
Простой, но неэффективный способ сделать это (дженерики не включены):
ArrayList baseArray = new ArrayList(Arrays.asList(array1));
baseArray.addAll(Arrays.asList(array2));
String concatenated[] = (String []) baseArray.toArray(new String[baseArray.size()]);
Простой вариант, позволяющий объединить более одного массива:
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()]);
}
Вариант, не зависящий от типа (ОБНОВЛЕНО - спасибо 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()));
}
Мне все еще больше нравится решение Иоахима Зауэра.
Я все еще использую Java 5, поэтому не могу использовать Arrays.copyOf (), как это делает Иоахим.
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;
}
Еще один основан на предложении 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;
}
Или с любимым Гуава:
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)Насколько я люблю Guava, метод из Apache Commons лучше справляется с значениями NULL.
Хотя использование библиотек - это хорошо, к сожалению, проблема была удалена. Следовательно, основное решение остается неуловимым.
В чем проблема с абстракцией? Не знаю, что здесь за изобретение колеса, если вы хотите узнать о проблеме, проверьте источник или прочитайте его. Профессиональный код должен использовать библиотеки высокого уровня, гораздо лучше, если он разработан внутри Google!
@RaviWallau Не могли бы вы указать ссылку на класс, который это делает?
@ SébastienTromp Это лучшее решение для этого вопроса - ArrayUtils.
Не советую добавлять Guava в проект только для конкатенации массивов, он большой и имеет серьезную нехватку модульности. @BrenoSalgado "Намного лучше, если он будет разработан внутри Google". Я категорически не согласен с этим.
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];
Вот моя слегка улучшенная версия 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;
}
Хорошая общая идея, но для всех, кто реализует: я бы предпочел версии copyOf и non-copyOf, чем те, которые делают и то, и другое посредством отражения.
Самый простой способ найти следующий:
List allFiltersList = Arrays.asList(regularFilters);
allFiltersList.addAll(Arrays.asList(preFiltersArray));
Filter[] mergedFilterArray = (Filter[]) allFiltersList.toArray();
Легко да. Но преобразование в список и из него звучит не очень эффективно.
Это преобразованная функция для массива 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;
}
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 типом / классом по своему вкусу
Я уверен, что это можно сделать короче и лучше, но это работает, и мне лень разбираться в этом дальше ...
Вы можете попробовать это
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;
}
Вы можете ввести свой массив !!!
resutlentArray? addTwoArray? Трудно читать код и комментарии в стиле YouTube !!!
Решение 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;
}
переработал мой для File [], но он такой же. Спасибо за ваше решение
Хотя, вероятно, довольно неэффективно.
Возможно, вы захотите добавить проверки null. И, возможно, установите некоторые из ваших переменных на final.
Проверки @TrippKinetics null будут скрывать NPE, а не показывать их, и использование final для локальных переменных не имеет никакой пользы (пока).
Лично я бы использовал здесь обычные петли for с индексом, а не for-each. Маловероятно, что это будет реорганизовано для использования списков (вы просто напишите другой метод), и for-each, скорее всего, будет медленнее, чем прямой доступ к массиву через индексацию. Nitpick: pos следует определять в пределах первого цикла for, а не за его пределами.
@Maarten Bodewes Я думаю, вы обнаружите (если вы проведете тест, который у меня есть), что for-each выполняется в то же время, что и индексированный цикл в поздних версиях Java. Оптимизатор позаботится об этом.
Как насчет просто
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 относятся к одному типу, это даст вам другой массив того же типа, содержащий оба массива.
По соображениям производительности я бы предварительно вычислил окончательный размер ArrayList, потому что ArrayList по определению выделяет новый массив и копирует его элементы каждый раз, когда текущий массив заполняется. В противном случае я бы сразу обратился к LinkedList, который не страдает такой проблемой.
Вот возможная реализация в рабочем коде решения псевдокода, написанного 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
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]);
}
}
В Haskell вы можете сделать что-то вроде [a, b, c] ++ [d, e], чтобы получить [a, b, c, d, e]. Это объединенные списки Haskell, но было бы очень приятно увидеть аналогичный оператор в Java для массивов. Вы так не думаете? Это элегантно, просто, универсально и не так уж сложно реализовать.
Если хотите, предлагаю вам взглянуть на работы Александра Христова в его Взлом компилятора OpenJDK. Он объясняет, как изменить исходный код javac для создания нового оператора. Его пример состоит в определении оператора **, где i ** j = Math.pow(i, j). Этот пример можно использовать для реализации оператора, объединяющего два массива одного типа.
Как только вы это сделаете, вы будете привязаны к своему настроенному javac для компиляции вашего кода, но сгенерированный байт-код будет понят любой JVM.
Конечно, вы можете реализовать свой собственный метод конкатенации массивов на исходном уровне, в других ответах есть много примеров того, как это сделать!
Можно добавить так много полезных операторов, что этот будет одним из них.
Вау круто! почему бы не изменить компилятор, чтобы решить проблему синтаксиса Java. :) смелый шаг!
Посмотрите на это элегантное решение (если вам нужен другой тип, кроме 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;
}
}
Вы можете объединить любое количество массивов.
Добро пожаловать в stackoverflow. Поскольку этот вопрос довольно старый, а System.arraycopy уже подробно обсуждался, лучше не восстанавливать старые потоки, если ответ не внесет в поток что-то важное.
Это не конкатенация, а копирование. В месте назначения уже должно быть достаточно места для размещения всех источников, иначе приведенный выше код вызовет исключение ArrayIndexOutOfBoundsException.
Я обнаружил, что мне пришлось иметь дело со случаем, когда массивы могут быть нулевыми ...
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;
}
Прошу простить меня за добавление еще одной версии в этот и без того длинный список. Я просмотрел каждый ответ и решил, что мне действительно нужна версия с одним параметром в подписи. Я также добавил некоторую проверку аргументов, чтобы извлечь выгоду из раннего отказа с разумной информацией в случае неожиданного ввода.
@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;
}
Я бы суммировал длину в том же цикле, в котором вы выполняете свою нулевую проверку, но это действительно хорошее резюме других ответов здесь. Я считаю, что он даже обрабатывает внутренние типы, такие как "int", не меняя их на объекты Integer, что на самом деле является ЕДИНСТВЕННОЙ причиной работать с ними как с массивами, а не просто менять все на ArrayLists. Также ваш метод может принимать 2 массива и параметр (...), чтобы вызывающий знал, что ему нужно передать как минимум два массива, прежде чем он запустит его и увидит ошибку, но это усложняет код цикла ....
Ух ты! здесь много сложных ответов, в том числе некоторые простые, которые зависят от внешних зависимостей. как насчет того, чтобы сделать это так:
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]);
..Но неэффективно и медленно.
Другой способ задуматься над вопросом. Чтобы объединить два или более массивов, нужно перечислить все элементы каждого массива, а затем построить новый массив. Это похоже на создание 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. Однако я думаю, что в этом есть своя красота.
String [] both = new ArrayList<String>(){{addAll(Arrays.asList(first)); addAll(Arrays.asList(second));}}.toArray(new String[0]);
Сложно, он компилируется, только если first и second являются окончательными
Истинный. Я подумал, что стоит добавить однострочник без внешней библиотеки.
ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));
both.toArray(new String[0]);
Ответ отличный, но немного неработающий. Чтобы сделать его идеальным, вы должны передать toArray () массив нужного вам типа. В приведенном выше примере код должен быть: both.toArray (new String [0]) См .: stackoverflow.com/questions/4042434/…
Не знаю, почему этот ответ не оценивается выше ... хотя, похоже, ему нужны изменения, предложенные @RonenRabinovici
Или лучше, без лишнего выделения массива нулевой длины: both.toArray(new String[both.size()]);)
@Honza рекомендуется прочитать
Привет @Honza, можно ли сделать то же самое, чтобы вернуть примитивный целочисленный массив в 3 строки?
Должен сделать свое дело. Предполагается, что сначала 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()]);
myList.addAll(new ArrayList<String>(Arrays.asList(second))); можно упростить до myList.addAll(Arrays.asList(second))
Этот работает только с 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];
}
Использование Stream в Java 8:
String[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b))
.toArray(String[]::new);
Или вот так, используя flatMap:
String[] both = Stream.of(a, b).flatMap(Stream::of)
.toArray(String[]::new);
Чтобы сделать это для универсального типа, вам нужно использовать отражение:
@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));
Насколько это эффективно?
Стоит прочитать: jaxenter.com/… tl; dr - потоки могут быть производительными или нет, это зависит от того, что вы с ними делаете, и ограничений проблемы (разве это не всегда ответ? Lol)
Да, это рискованное решение с точки зрения производительности. Это может быть быстро, но я бы не стал ставить на это производительность моего приложения;)
Кроме того, если а или б являются массивами примитивных типов, их потоки должны быть .boxed(), поэтому они имеют тип Stream, а не, например, IntStream, который нельзя передать в качестве параметра Stream.concat.
@Will Hardwick-Smith: нет, вам нужно только выбрать правильный класс потока, например если a и b являются int[], используйте int[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
@Supuhstar: Наверное, не так быстро, как System.arrayCopy. Но и не особо медленный. Вероятно, вам придется делать это очень много раз с массивами огромный в контекстах, чувствительных к производительности В самом деле, чтобы разница во времени выполнения имела значение.
Интересно, что быстрее и эффективнее с точки зрения памяти: метод concat или flatMap? Или они под капотом такие же?
Последнее решение хорошо, потому что его можно использовать более чем для двух массивов, в отличие от большинства (если не всех) других ответов.
@SinaMadani со всеми известными реализациями, вариант, использующий concat, будет быстрее и потребует меньше памяти, потому что он может заранее предсказать размер результирующего массива и будет создавать и заполнять только один массив. Напротив, решение на основе flatMap должно будет использовать внутренний буфер с изменяемым размером, по крайней мере, с одним заключительным этапом копирования.
Можно ли заставить его работать для общего типа (как в ответе выше)? Что-то вроде T[] both = Stream.of(a, b).flatMap(Stream::of).toArray(T[]::new); Похоже, что T[]::new недопустима причина стирания типа ...
@ArtsiomChapialiou: Можно, но это не так красиво. Вы должны использовать отражение для создания массива и, таким образом, получить неконтролируемое приведение. Я добавил это в текст решения.
Я думаю, что лучшим решением с дженериками было бы:
/* 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;
}
Это похоже на полезный код и захватывает как объекты, так и базовые типы. Однако я бы не стал называть функцию resizeArray, потому что размер массивов не можешь можно изменять в Java. Вот почему Arrays.copyOf делает то же самое, но с другим именем метода.
Не совсем, copyOf просто делает копию той же длины, если вы внимательно прочитаете код, вы поймете, что функция получает параметр newSize, поэтому resizeArray делает именно это, возвращает массив с измененным размером.
Как насчет :
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()]);
}
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;
}
Это очень запутанно, трудно понять, недокументировано и - с двумя операторами if в цикле - также довольно неэффективно.
Вы можете попробовать преобразовать его в Arraylist и использовать метод addAll, а затем преобразовать обратно в массив.
List list = new ArrayList(Arrays.asList(first));
list.addAll(Arrays.asList(second));
String[] both = list.toArray();
Хорошее решение - было бы лучше, если бы код был реорганизован, чтобы полностью отказаться от массивов в пользу ArrayLists, но это выходит за рамки контроля «Ответа» и до спрашивающего.
Считаю, что для работы требуется 4 дополнительных временных объекта.
@rghome, по крайней мере, для реализации такой простой задачи не требуется дополнительная библиотека
Другой способ с 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);
}
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()]);
}
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;
Каждый ответ - это копирование данных и создание нового массива. Это не является строго необходимым и определенно НЕ то, что вы хотите делать, если ваши массивы достаточно большие. Создатели 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
}
Вот код от 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"]
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.
Работает достаточно качественно.
Пустая трата процессора и памяти. См. Ответ от @ Douglas-Held
Если вы используете этот способ, вам не нужно импортировать какой-либо сторонний класс.
Если вы хотите объединить String
Пример кода для объединения двух строковых массивов
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
Пример кода для объединения двух целочисленных массивов
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));
}
}
Мы можем использовать и этот способ.
Еще один ответ для любителей алгоритмов:
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]
Оператор if для каждой копии - не лучшая идея, так как она сильно снизит производительность.
@MaartenBodewes всегда приятно изучать новые подходы, ориентированные на производительность. Есть предложения по улучшению этого?
Ну да, arrayCopy, но я полагаю, что это упоминалось во многих других примерах. То же самое для двух или более шлейфов for; можно вывести ветвление (операторы if) из цикла.
Вы можете попробовать этот метод, который объединяет несколько массивов:
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;
}
Вы можете добавить два массива в две строки кода.
String[] both = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, both, first.length, second.length);
Это быстрое и эффективное решение, которое будет работать для примитивных типов, так как два задействованных метода перегружены.
Вам следует избегать решений, связанных со списками ArrayLists, потоками и т. д., Поскольку им потребуется выделять временную память без какой-либо полезной цели.
Следует избегать циклов for для больших массивов, поскольку они неэффективны. Встроенные методы используют чрезвычайно быстрые функции блочного копирования.
Это одно из лучших решений. 100% стандартная Java. Быстро / эффективно. Должно быть больше голосов!
Однозначно лучшее решение.
Это должен быть принятый ответ "более эффективный"
В 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));
}
Это то же самое, что и предыдущий ответ 10 16 февраля.
@rghome Вы можете ссылаться на ответы, нажав кнопку «Поделиться». Основной, почему бы не удалить ответ, если есть явная ложь более ранней даты? При желании можно улучшить существующий, если там чего-то не хватает.
Решение, отличное от 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;
}
Используя потоки Java 8+, вы можете написать следующую функцию:
private static String[] concatArrays(final String[]... arrays) {
return Arrays.stream(arrays)
.flatMap(Arrays::stream)
.toArray(String[]::new);
}
Это должно быть однострочное.
public String [] concatenate (final String array1[], final String array2[])
{
return Stream.concat(Stream.of(array1), Stream.of(array2)).toArray(String[]::new);
}
Общая статическая версия, которая использует высокопроизводительный 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;
}
Вероятно, это единственный универсальный и безопасный для типов способ:
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
объединяет серию массивов компактных, быстрых и типобезопасных с лямбда
@SafeVarargs
public static <T> T[] concat( T[]... arrays ) {
return( Stream.of( arrays ).reduce( ( arr1, arr2 ) -> {
T[] rslt = Arrays.copyOf( arr1, arr1.length + arr2.length );
System.arraycopy( arr2, 0, rslt, arr1.length, arr2.length );
return( rslt );
} ).orElse( null ) );
};
возвращает null при вызове без аргументов
например. пример с 3 массивами:
String[] a = new String[] { "a", "b", "c", "d" };
String[] b = new String[] { "e", "f", "g", "h" };
String[] c = new String[] { "i", "j", "k", "l" };
concat( a, b, c ); // [a, b, c, d, e, f, g, h, i, j, k, l]
«… Вероятно, единственный универсальный и безопасный для типов способ» - адаптировано:
Number[] array1 = { 1, 2, 3 };
Number[] array2 = { 4.0, 5.0, 6.0 };
Number[] array = concat( array1, array2 ); // [1, 2, 3, 4.0, 5.0, 6.0]
Просто хотел добавить, вы тоже можете использовать System.arraycopy:
import static java.lang.System.out;
import static java.lang.System.arraycopy;
import java.lang.reflect.Array;
class Playground {
@SuppressWarnings("unchecked")
public static <T>T[] combineArrays(T[] a1, T[] a2) {
T[] result = (T[]) Array.newInstance(a1.getClass().getComponentType(), a1.length+a2.length);
arraycopy(a1,0,result,0,a1.length);
arraycopy(a2,0,result,a1.length,a2.length);
return result;
}
public static void main(String[ ] args) {
String monthsString = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";
String[] months = monthsString.split("(?<=\G.{3})");
String daysString = "SUNMONTUEWEDTHUFRISAT";
String[] days = daysString.split("(?<=\G.{3})");
for (String m : months) {
out.println(m);
}
out.println("== = ");
for (String d : days) {
out.println(d);
}
out.println("== = ");
String[] results = combineArrays(months, days);
for (String r : results) {
out.println(r);
}
out.println("== = ");
}
}
Вот что у меня сработало:
String[] data=null;
String[] data2=null;
ArrayList<String> data1 = new ArrayList<String>();
for(int i=0; i<2;i++) {
data2 = input.readLine().split(",");
data1.addAll(Arrays.asList(data2));
data= data1.toArray(new String[data1.size()]);
}
Я использую следующий метод для объединения любого количества массивов одного типа с использованием java 8:
public static <G> G[] concatenate(IntFunction<G[]> generator, G[] ... arrays) {
int len = arrays.length;
if (len == 0) {
return generator.apply(0);
} else if (len == 1) {
return arrays[0];
}
int pos = 0;
Stream<G> result = Stream.concat(Arrays.stream(arrays[pos]), Arrays.stream(arrays[++pos]));
while (pos < len - 1) {
result = Stream.concat(result, Arrays.stream(arrays[++pos]));
}
return result.toArray(generator);
}
использование:
concatenate(String[]::new, new String[]{"one"}, new String[]{"two"}, new String[]{"three"})
или же
concatenate(Integer[]::new, new Integer[]{1}, new Integer[]{2}, new Integer[]{3})
Я только что обнаружил этот вопрос, извините, очень поздно, и увидел много ответов, которые были слишком далеки, используя определенные библиотеки, используя функцию преобразования данных из массива в поток и обратно в массив и так далее. Но, мы можем просто использовать простой цикл, и проблема решена
public String[] concat(String[] firstArr,String[] secondArr){
//if both is empty just return
if (firstArr.length==0 && secondArr.length==0)return new String[0];
String[] res = new String[firstArr.length+secondArr.length];
int idxFromFirst=0;
//loop over firstArr, idxFromFirst will be used as starting offset for secondArr
for(int i=0;i<firstArr.length;i++){
res[i] = firstArr[i];
idxFromFirst++;
}
//loop over secondArr, with starting offset idxFromFirst (the offset track from first array)
for(int i=0;i<secondArr.length;i++){
res[idxFromFirst+i]=secondArr[i];
}
return res;
}
Все, правда? он не сказал, что его волнует порядок или что-то в этом роде. Это должен быть самый простой способ.
Bytes.concat из Guava