我需要在Java中连接两个字符串数组。

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

哪种方法最简单?


当前回答

应该会成功的。这是假设String[]第一个,String[]第二个

List<String> myList = new ArrayList<String>(Arrays.asList(first));
myList.addAll(new ArrayList<String>(Arrays.asList(second)));
String[] both = myList.toArray(new String[myList.size()]);

其他回答

请原谅我在这个已经很长的列表中添加了另一个版本。我看了每一个答案,决定我真的想要一个签名中只有一个参数的版本。我还添加了一些参数检查,以从早期失败中受益,并在出现意外输入时提供合理的信息。

@SuppressWarnings("unchecked")
public static <T> T[] 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 baseArray = new ArrayList(Arrays.asList(array1));
baseArray.addAll(Arrays.asList(array2));
String concatenated[] = (String []) baseArray.toArray(new String[baseArray.size()]);

在Haskell中,您可以执行类似[a,b,c]++[d,e]的操作来获得[a,b,c,d,e]。这些是连接起来的Haskell列表,但很高兴看到Java中的类似运算符用于数组。你不这么认为吗?这是优雅、简单、通用的,而且实现起来并不那么困难。

如果你愿意,我建议你看看Alexander Hristov在破解OpenJDK编译器方面的工作。他解释了如何修改javac源代码以创建新的运算符。他的示例包括定义一个'**'运算符,其中i**j=Math.pow(i,j)。我们可以用这个例子来实现一个连接两个相同类型数组的运算符。

这样做之后,您就绑定到定制的javac来编译代码,但是任何JVM都可以理解生成的字节码。当然,您可以在源代码级别实现自己的数组连接方法,其他答案中有很多关于如何实现的示例!有这么多有用的运算符可以添加,这一个将是其中之一。

我发现我必须处理数组可以为空的情况。。。

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

我最近一直在与过度的记忆循环作斗争。如果已知a和/或b通常是空的,这里是silvertab代码的另一种修改(也被通用化):

private static <T> T[] 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;
}

编辑:这篇文章的前一个版本指出,像这样的数组重用应该清楚地记录下来。正如Maarten在评论中指出的那样,一般来说,最好删除if语句,这样就不需要文档了。但话说回来,那些if语句首先就是这个特定优化的要点。我会在这里留下这个答案,但要小心!