在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个回答

4

另一种思考这个问题的方式是,要连接两个或多个数组,需要做的就是列出每个数组的所有元素,然后构建一个新数组。这听起来像是创建一个 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的解决方案。然而,我认为这个代码有其自己的优美之处。


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

3
我发现我必须处理数组可能为空的情况...
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;
}

3
每一个答案都是在复制数据并创建一个新的数组。这并非完全必要,如果您的数组相当大,那么绝对不是您想要做的事情。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
}

3
String [] both = new ArrayList<String>(){{addAll(Arrays.asList(first)); addAll(Arrays.asList(second));}}.toArray(new String[0]);

2
棘手的问题,只有在firstsecond是final的情况下才会编译。 - orique
1
没错。我认为值得添加一个不需要外部库的一行代码。 - Frimousse

3
一种简单但效率低下的方法是(不包括泛型):
ArrayList baseArray = new ArrayList(Arrays.asList(array1));
baseArray.addAll(Arrays.asList(array2));
String concatenated[] = (String []) baseArray.toArray(new String[baseArray.size()]);

3
一种类型无关的变化(更新 - 感谢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()));
}

我仍然更喜欢Joachim Sauer的解决方案。 - Michael Myers
我仍在使用Java 5,因此无法像Joachim一样使用Arrays.copyOf()。 - Damo

3

使用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[](甚至是零个数组)。


17
因为创建了许多不必要的列表对象,所以我不得不给这个投票点个踩。 - Tim Frey

2
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。
我相信这可以更简洁、更好,但它能工作,而且我懒得再进一步整理了...

2

这是基于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;
}

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