我需要String
在Java中连接两个数组.
void f(String[] first, String[] second) { String[] both = ??? }
最简单的方法是什么?
我从优秀的旧的Apache Commons Lang库中找到了一个单行解决方案.
ArrayUtils.addAll(T[], T...)
码:
String[] both = ArrayUtils.addAll(first, second);
这是一个简单的方法,它将连接两个数组并返回结果:
publicT[] 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 staticT 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 6,因为它们使用Arrays.copyOf()
两个版本都避免创建任何中间List
对象,并用于System.arraycopy()
确保尽可能快地复制大型数组.
对于两个数组,它看起来像这样:
public staticT[] 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 staticT[] 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; }
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);
或者与心爱的番石榴:
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)
使用Java API:
String[] f(String[] first, String[] second) { Listboth = new ArrayList (first.length + second.length); Collections.addAll(both, first); Collections.addAll(both, second); return both.toArray(new String[both.size()]); }
您可以将这两个数组附加到两行代码中.
String[] both = Arrays.copyOf(first, first.length + second.length); System.arraycopy(second, 0, both, first.length, second.length);
这是一种快速有效的解决方案,适用于原始类型,并且所涉及的两种方法都是重载的.
您应该避免涉及ArrayLists,流等的解决方案,因为这些解决方案需要分配临时内存而没有用处.
您应该避免for
大型数组的循环,因为这些循环效率不高.内置方法使用极快的块复制功能.
一个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; }
我最近在内存轮换过多的情况下遇到了问题.如果已知a和/或b通常是空的,那么这是另一个silvertab代码的修改(也是通用的):
private staticT[] 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; }
(在任何一种情况下,数组重用行为都应该是明确的JavaDoced!)
的功能的Java库具有装备有方便的方法,如级联阵列的阵列包装类.
import static fj.data.Array.array;
...然后
Arrayboth = array(first).append(array(second));
要取出展开的阵列,请致电
String[] s = both.array();
ArrayListboth = new ArrayList(Arrays.asList(first)); both.addAll(Arrays.asList(second)); both.toArray(new String[0]);
这是对silvertab解决方案的改编,改进了仿制药:
staticT[] 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解决方案的回答.它不仅消除了警告; 它也更短,更高效,更容易阅读!
Java8使用Stream的另一种方式
public String[] concatString(String[] a, String[] b){ StreamstreamA = Arrays.stream(a); Stream streamB = Arrays.stream(b); return Stream.concat(streamA, streamB).toArray(String[]::new); }
如果您使用这种方式,则无需导入任何第三方类.
如果你想连接 String
用于连接两个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
用于连接两个整数数组的示例代码
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; }
这是Main方法
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)); } }
我们也可以用这种方式.
请原谅我在这个已经很久的列表中添加了另一个版本.我查看了每个答案,并决定我真的想要一个只有一个参数的签名版本.我还添加了一些参数检查,以便在意外输入的情况下通过合理的信息从早期故障中受益.
@SuppressWarnings("unchecked") public staticT[] 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; }
您可以尝试将其转换为Arraylist并使用addAll方法然后转换回数组.
List list = new ArrayList(Arrays.asList(first)); list.addAll(Arrays.asList(second)); String[] both = list.toArray();
这里是在silvertab编写的伪代码解决方案的工作代码中的可能实现.
谢谢silvertab!
public class Array {
public static T[] concat(T[] a, T[] b, ArrayBuilderI 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 {
public T[] build(int size);
}
这是一个实现接口的具体构建器,构建一个Integer
数组:
public class IntegerArrayBuilder implements ArrayBuilderI {
@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]);
}
}
使用Java 8+流,您可以编写以下函数:
private static String[] concatArrays(final String[]... arrays) { return Arrays.stream(arrays) .flatMap(Arrays::stream) .toArray(String[]::new); }
这有效,但您需要插入自己的错误检查.
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之外的任何东西.
哇!这里有很多复杂的答案,包括一些依赖外部依赖的简单答案.怎么样这样做:
String [] arg1 = new String{"a","b","c"}; String [] arg2 = new String{"x","y","z"}; ArrayListtemp = new ArrayList (); temp.addAll(Arrays.asList(arg1)); temp.addAll(Arrays.asList(arg2)); String [] concatedArgs = temp.toArray(new String[arg1.length+arg2.length]);
这应该是单线的。
public String [] concatenate (final String array1[], final String array2[]) { return Stream.concat(Stream.of(array1), Stream.of(array2)).toArray(String[]::new); }
这是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; }
怎么样简单
public static class Array { public staticT[] concat(T[]... arrays) { ArrayList al = new ArrayList (); for (T[] one : arrays) Collections.addAll(al, one); return (T[]) al.toArray(arrays[0].clone()); } }
就这么做Array.concat(arr1, arr2)
.只要arr1
和arr2
属于同一类型,这将为您提供包含两个数组的相同类型的另一个数组.