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

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

哪种方法最简单?


当前回答

一个与类型无关的变体(已更新-感谢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()));
}

其他回答

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

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

另一个基于SilverTab的建议,但它支持x个参数,不需要Java6。它也不是通用的,但我确信它可以是通用的。

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

这里是silvertab编写的伪代码解决方案的工作代码中的一个可能实现。

谢谢silvertab!

public class Array {

   public static <T> T[] concat(T[] a, T[] b, ArrayBuilderI<T> 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中不可能这样做

新T[尺寸]

由于通用类型擦除:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

这里是一个实现接口的具体构建器,构建一个整数数组:

public class IntegerArrayBuilder implements ArrayBuilderI<Integer> {

   @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 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