如何在Java中连接两个数组?
我需要在Java中串联两个String数组。
void f(String[] first, String[] second) { String[] both = ??? }
最简单的方法是什么?
解决方案
回答
这是一个简单的方法,它将两个数组连接起来并返回结果:
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 }));
回答
我从旧的Apache Commons Lang库中找到了单行解决方案。ArrayUtils.addAll(T [],T ...)
代码:
String[] both = (String[])ArrayUtils.addAll(first, second);
回答
Functional Java库具有一个数组包装器类,该类为数组配备了诸如连接之类的便捷方法。
import static fj.data.Array.array;
...接着
Array<String> both = array(first).append(array(second));
要取出未包装的阵列,请致电
String[] s = both.array();
回答
仅使用Java自己的API:
String[] join(String[]... arrays) { // calculate size of target array int size = 0; for (String[] array : arrays) { size += array.length; } // create list of appropriate size java.util.List list = new java.util.ArrayList(size); // add arrays for (String[] array : arrays) { list.addAll(java.util.Arrays.asList(array)); } // create and return final array return list.toArray(new String[size]); }
现在,此代码并不是最有效的,但它仅依赖于标准Java类,并且易于理解。它适用于任意数量的String 。
回答
这是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解决方案的信息,请参见Joachim的答案。它不仅消除了警告,而且消除了警告。它更短,更有效且更易于阅读!
回答
最近,我与过多的内存轮换问题进行了斗争。如果已知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!)
回答
使用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()]); }
回答
如果我们想在解决方案中使用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(); } }
它可能不是最有效的,但是除了Java自己的API外,它不依赖任何其他东西。
回答
可以编写一个完全通用的版本,甚至可以扩展为连接任意数量的数组。这个版本需要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; }
回答
一种简单但效率低下的方法(不包括泛型):
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())); }
回答
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; }