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

1577

我需要在Java中合并两个String数组。

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

最简单的方法是什么?


4
Guava 中的 Bytes.concat 函数 - Ben Page
2
我看到这里有很多回复,但问题用词不当(“最简单的方法”?)无法表明最佳答案... - Artur Opalinski
3
这里有数十个答案将数据复制到一个新数组中,因为这是要求的 - 但是当不是严格必要时复制数据是一件坏事,特别是在Java中。相反,跟踪索引并将这两个数组视为已连接即可。我添加了一个说明这种技术的解决方案。 - Douglas Held
47
这个问题目前有50个不同的答案,让我想知道为什么Java从未提供一个简单的array1 + array2连接函数。 - JollyJoker
2
你可以用两行标准的Java代码完美高效地实现它(请参见我的答案),因此使用单个方法并不能获得太多好处。所有这些奇怪而神奇的解决方案都有点浪费时间。 - rghome
显示剩余2条评论
66个回答

6

哇!这里有很多复杂的答案,包括一些依赖外部依赖项的简单答案。我们可以像这样实现:

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

1
但效率低下且缓慢。 - Jonas Czech

6

一个通用的静态版本,使用高性能的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;
}

5
如何简单地呢?
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)。只要arr1arr2类型相同,这将给您另一个包含两个数组的相同类型的数组。


1
出于性能考虑,我会预先计算ArrayList的最终大小,因为按照定义,ArrayList在当前数组已满时会分配一个新数组并复制其元素。否则,我会直接选择LinkedList,因为它不会遇到这样的问题。 - usr-local-ΕΨΗΕΛΩΝ

5
这是一个用于字符串数组的转换函数:
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;
}

5

一种简单的变化,允许连接多个数组:

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

4
怎么样?
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()]);
}

4

这是我稍微改进过的Joachim Sauer的concatAll方法。它可以在Java 5或6上运行,如果运行时有Java 6的System.arraycopy,则会使用该方法。这个方法(在我看来)非常适合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;
  }

1
好的一般想法,但对于任何实现者来说:我更喜欢有一个copyOf和一个非copyOf版本,而不是通过反射同时执行两个版本。 - rektide

4
这里是由 abacus-common 提供的代码。
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"]

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

4

这可能是唯一的通用和类型安全的方法:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接