协慌网

登录 贡献 社区

如何在 Java 中连接两个数组?

我需要在 Java 中连接两个String数组。

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

最简单的方法是什么?

答案

我从优秀的旧的 Apache Commons Lang 库中找到了一个单行解决方案。
ArrayUtils.addAll(T[], T...)

码:

String[] both = (String[])ArrayUtils.addAll(first, second);

这是一个简单的方法,它将连接两个数组并返回结果:

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