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


1366

我需要连接StringJava中的两个数组。

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

最简单的方法是什么?


3
来自番石榴的Bytes.concat
Ben Page

1
我在这里看到了很多回应,但问题措辞如此(“最简单的方式”?)以致于无法给出最佳答案……
Artur Opalinski

2
这里有几十个答案正在将数据复制到一个新数组中,因为这是需要的-但是在并非绝对必要时复制数据是一件不好的事情,尤其是在Java中。相反,请跟踪索引并使用两个数组,就好像它们被连接了一样。我添加了一个说明该技术的解决方案。
道格拉斯

12
像这样的问题目前有50个不同的答案,这一事实使我想知道为什么Java从来没有简单的array1 + array2串联。
JollyJoker

2
您可以在两行标准Java中完美,高效地完成它(请参见我的回答),因此,只有一种方法可以完成很多工作。所有这些奇异而奇妙的解决方案都浪费时间。
rghome

Answers:


1093

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

码:

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

175
如果回答了问题,它是如何“作弊”的?当然,对于这种特定情况,拥有额外的依赖关系可能是过大的,但是在声明它存在的情况下并没有造成任何危害,尤其是因为Apache Commons中有很多出色的功能。
罗布

33
我同意,这并没有真正回答问题。高级库可能很棒,但是如果您想学习一种高效的方法,则需要查看库方法正在使用的代码。同样,在许多情况下,您不能只是动态访问产品中的另一个库。
AdamC

76
我认为这是一个很好的答案。还提供了POJO解决方案,但是如果OP已在其程序中使用Apache Commons(考虑到其受欢迎程度,则可能会完全使用),他可能仍然不知道该解决方案。这样,他就不会“为此方法添加依赖项”,而是会更好地利用现有库。
亚当

14
如果您始终担心不为单个方法添加库,则永远不会添加任何新库。鉴于Apache Commons中存在出色的实用程序,我强烈建议在出现第一个用例时将其添加。
Hindol

6
我从来不认为使用Apache Commons是“作弊”。
Jery​​l Cook

768

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

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

1
我喜欢这个建议,因为它较少依赖最新的Java版本。在我的项目中,我经常卡在较旧版本的Java或CLDC概要文件中,而其中某些工具(如Antti提到的那些工具)不可用。
kvn 2011年

4
以下行将打破通用部分:concatenate(new String [] {“ 1”},new Object [] {new Object()})
dragon66 2015年

不必使用@SuppressWarnings注释会很好-我将在下面发布解决方案。
beaudet

为+1 Array.newInstance(a.getClass().getComponentType(), aLen + bLen);。令人惊讶的是,我从未见过如此。@beaudet我认为注释在这里很好,考虑到为什么它被抑制了。
布莱克

1
哈,称我为纯粹主义者,但我更喜欢不需要删除警告就可以删除警告的简洁代码
beaudet

475

可以编写一个完全通用的版本,甚至可以扩展为连接任意数量的数组。此版本需要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;
}

10
@djBO:对于原始类型的数组,您需要为每种类型进行重载:只需复制代码,然后将其替换Tbyte(并丢失<T>)。
Joachim Sauer

您能否告诉我如何在课堂上使用<T>运算符类型?
Johnydep 2011年

6
我将其添加到开头,只是为了防御。if(first == null){if(second == null){返回null; }返回第二;} if(second == null){首先返回;}
马拉松

4
@djBo:怎么样:ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(array1); buffer.put(array2); return buffer.array();
萨姆·戈德堡

18
还有在这种方法中如果调用这些功能与不同的组件类型的数组,例如,其变得明显的错误concat(ai, ad),其中,aiInteger[]adDouble[]。(在这种情况下,类型参数由编译器<T>解析<? extends Number>。)创建的数组Arrays.copyOf将具有第一个数组的组件类型,即Integer在此示例中。当该函数将要复制第二个数组时,ArrayStoreException将引发an 。解决方案是有一个附加Class<T> type参数。
T公牛

457

Stream在Java 8中使用:

String[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b))
                      .toArray(String[]::new);

或者像这样,使用flatMap

String[] both = Stream.of(a, b).flatMap(Stream::of)
                      .toArray(String[]::new);

为此,您必须使用反射:

@SuppressWarnings("unchecked")
T[] both = Stream.concat(Arrays.stream(a), Arrays.stream(b)).toArray(
    size -> (T[]) Array.newInstance(a.getClass().getComponentType(), size));

28
这有多有效?
Supuhstar

8
值得一读:jaxenter.com/…tl ; dr-流是否有效,这取决于您对它们的处理方式以及问题的约束(这是否总是答案?大声笑)
Trevor Brown

6
此外,如果ab是原始类型的数组,则它们的流将需要是.boxed()其类型,Stream而不是例如IntStream不能将其作为参数传递给的类型Stream.concat
Will Hardwick-Smith

17
@Will Hardwick-Smith:不,您只需要选择正确的流类,例如if abare int[],使用int[] both = IntStream.concat(Arrays.stream(a), Arrays.stream(b)).toArray();
Holger

3
@Supuhstar:速度可能不如System.arrayCopy。但也不是特别慢。你可能不得不这样做一个非常有许多次巨大的阵列,在真正的执行时间差不要紧性能要求较高的环境。
Lii

191

或与心爱的番石榴

String[] both = ObjectArrays.concat(first, second, String.class);

此外,还有原始数组的版本:

  • Booleans.concat(first, second)
  • Bytes.concat(first, second)
  • Chars.concat(first, second)
  • Doubles.concat(first, second)
  • Shorts.concat(first, second)
  • Ints.concat(first, second)
  • Longs.concat(first, second)
  • Floats.concat(first, second)

尽管我非常喜欢Guava,但Apache Commons的方法在处理nullable方面效果更好。
拉维·瓦劳

7
虽然使用库很好,但是不幸的是问题已经被抽象出来了。因此,基本解决方案仍然难以捉摸。
user924272 2014年

51
抽象有什么问题?Dunno在这里重新发明轮子有什么用,如果您想了解问题,请检查源代码或继续阅读。专业代码应该使用高级库,如果它是在Google内部开发的,那就更好了!
Breno Salgado 2014年

@RaviWallau您可以链接到执行此操作的课程吗?
塞巴斯蒂安·特朗

1
@SébastienTromp这是此问题的最佳解决方案-ArrayUtils。
拉维·瓦劳

70

您可以在两行代码中附加两个数组。

String[] both = Arrays.copyOf(first, first.length + second.length);
System.arraycopy(second, 0, both, first.length, second.length);

这是一种快速有效的解决方案,将适用于原始类型以及所涉及的两种方法都已重载。

您应避免使用涉及ArrayList,流等的解决方案,因为这些将需要分配临时内存,而无用。

您应该避免for大型数组的循环,因为它们效率不高。内置方法使用极快的块复制功能。


1
这是最好的解决方案之一。100%标准Java。快速/高效。应该获得更多投票!
Shebla Tsama

58

使用Java API:

String[] f(String[] first, String[] second) {
    List<String> both = new ArrayList<String>(first.length + second.length);
    Collections.addAll(both, first);
    Collections.addAll(both, second);
    return both.toArray(new String[both.size()]);
}

13
很简单,但是效率很低,因为它为ArrayList创建了一个数组,然后为toArray方法生成了另一个。但是仍然很有效,因为它很容易阅读。
PhoneixS 2014年

1
适用于字符串和对象(根据需要),但没有用于主要类型的addAll方法(如ints)
joro

本文所述,使用both.toArray(new String[0])会比更快both.toArray(new String[both.size()]),即使它违背了我们的天真直觉。这就是为什么在优化时衡量实际性能如此重要的原因。或者,当无法证明更复杂的变体的优势时,只需使用更简单的结构即可。
Holger

42

溶液100%的旧Java System.arraycopy(在GWT客户端例如不可用):

static String[] concat(String[]... arrays) {
    int length = 0;
    for (String[] array : arrays) {
        length += array.length;
    }
    String[] result = new String[length];
    int pos = 0;
    for (String[] array : arrays) {
        for (String element : array) {
            result[pos] = element;
            pos++;
        }
    }
    return result;
}

重做了File []的代码,但是是一样的。感谢您的解决方案
ShadowFlame 2012年

5
不过可能效率很低。
JonasCz-恢复莫妮卡2015年

您可能要添加null支票。也许将一些变量设置为final
Tripp Kinetics 2015年

@TrippKinetics null检查将隐藏NPE,而不是显示它们,并且将final用于本地var没有任何好处(尚未)。
Maarten Bodewes,

1
@Maarten Bodewes我想您会发现(如果对它进行基准测试,我有的话)for-each在Java的较新版本上与索引循环同时运行。优化器会处理它。
rghome

33

我最近与过多的内存轮换问题进行了斗争。如果已知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语句首先是特定优化的重点。我会在这里留下这个答案,但要小心!


5
但是,这意味着您将返回相同的数组,并且在返回的数组上更改值将在返回的输入数组的相同位置更改该值。
洛伦佐·波卡恰

是的-请参阅我的文章末尾有关数组重用的评论。在我们的特定情况下,此解决方案带来的维护开销值得,但在大多数情况下可能应使用防御性复制。
凌空

Lorenzo / volley,您能解释一下代码中导致数组重用的哪一部分?我以为System.arraycopy复制数组的内容?
罗迪·卡西姆

4
调用者通常希望对concat()的调用返回一个新分配的数组。如果a或b为null,则concat()将返回传递给它的数组之一。这种重用可能是意外的。(是的,arraycopy只复制。重用来自直接返回a或b。)
凌空

代码应尽可能自我解释。读代码的人不必查找被调用函数的JavaDoc即可发现它对一种特定条件起了某件事,而对另一种条件起了别的作用。简而言之:您通常无法通过注释解决此类设计问题。仅保留这两个if语句将是最简单的解决方法。
Maarten Bodewes

27

功能的Java库具有装备有方便的方法,如级联阵列的阵列包装类。

import static fj.data.Array.array;

...然后

Array<String> both = array(first).append(array(second));

要取出未包装的阵列,请致电

String[] s = both.array();

27
ArrayList<String> both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));

both.toArray(new String[0]);

3
答案很好,但有点破。为了使其完美,您应该将所需类型的数组传递给toArray()。另外,在上述例子中,代码应该是:both.toArray(新的String [0])参见:stackoverflow.com/questions/4042434/...
罗南Rabinovici

不知道为什么这个答案没有得到更高的评价……尽管它似乎需要@RonenRabinovici建议的更改
drmrbrewer

4
或更好,没有不必要的零长度数组分配:both.toArray(new String[both.size()]);)
Honza

1
@Honza 建议阅读
Holger

嗨,@ Honza,可能做同样的事情来返回3行中的原始整数数组吗?
jumping_monkey

18

使用Stream的Java8的另一种方式

  public String[] concatString(String[] a, String[] b){ 
    Stream<String> streamA = Arrays.stream(a);
    Stream<String> streamB = Arrays.stream(b);
    return Stream.concat(streamA, streamB).toArray(String[]::new); 
  }

17

这是silvertab解决方案的改编,其中改进了泛型:

static <T> T[] concat(T[] a, T[] b) {
    final int alen = a.length;
    final int blen = b.length;
    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;
}

注意:有关Java 6解决方案的信息,请参见Joachim的答案。它不仅消除了警告;它更短,更有效且更易于阅读!


您可以取消此方法的警告,但除此之外,您无能为力。数组和泛型并没有真正混合使用。
Dan Dyer

3
如果使用Arrays.copyOf(),则可以消除未经检查的警告。见我的答案的实现。
约阿希姆·绍尔

@SuppressWarnings(“ unchecked”)
Mark Renouf

13

如果您使用这种方式,则无需导入任何第三方类。

如果要串联 String

连接两个字符串数组的示例代码

public static String[] combineString(String[] first, String[] second){
        int length = first.length + second.length;
        String[] result = new String[length];
        System.arraycopy(first, 0, result, 0, first.length);
        System.arraycopy(second, 0, result, first.length, second.length);
        return result;
    }

如果要串联 Int

连接两个整数数组的示例代码

public static int[] combineInt(int[] a, int[] b){
        int length = a.length + b.length;
        int[] result = new int[length];
        System.arraycopy(a, 0, result, 0, a.length);
        System.arraycopy(b, 0, result, a.length, b.length);
        return result;
    }

这是主要方法

    public static void main(String[] args) {

            String [] first = {"a", "b", "c"};
            String [] second = {"d", "e"};

            String [] joined = combineString(first, second);
            System.out.println("concatenated String array : " + Arrays.toString(joined));

            int[] array1 = {101,102,103,104};
            int[] array2 = {105,106,107,108};
            int[] concatenateInt = combineInt(array1, array2);

            System.out.println("concatenated Int array : " + Arrays.toString(concatenateInt));

        }
    }  

我们也可以使用这种方式。


11

请原谅我为这个已经很长的列表添加了另一个版本。我查看了每个答案,并决定我真的想要一个签名中仅包含一个参数的版本。我还添加了一些参数检查功能,以便在意外输入的情况下从早期失败中获得明智的信息。

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

我将在执行空检查的同一循环中总结长度,但这是这里其他答案的很好的总结。我相信它甚至可以处理诸如“ int”之类的内部类型,而无需将其更改为Integer对象,这实际上是将它们作为数组处理的唯一原因,而不仅仅是将所有内容更改为ArrayLists。同时你的方法可能需要2个阵列和一个(...)参数,以便调用者知道他需要至少两个阵列通过他运行它,看到的错误之前,但该循环的代码复杂....
比尔ķ

11

您可以尝试将其转换为Arraylist并使用addAll方法,然后再转换回数组。

List list = new ArrayList(Arrays.asList(first));
  list.addAll(Arrays.asList(second));
  String[] both = list.toArray();

好的解决方案-如果将代码重构为完全避免使用ArrayList来支持数组,那会更好,但是这超出了“答案”的控制范围,而超出了发问者的范围。
Bill K

我认为这需要另外4个临时对象才能工作。
rghome

@rghome,至少不需要额外的库来实现这样的简单任务
Farid

9

使用Java 8+流,您可以编写以下函数:

private static String[] concatArrays(final String[]... arrays) {
    return Arrays.stream(arrays)
         .flatMap(Arrays::stream)
         .toArray(String[]::new);
}

7

这是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中无法执行

new T[size]

由于泛型类型擦除:

public interface ArrayBuilderI<T> {

   public T[] build(int size);
}

这里是一个具体的构建器,实现了该接口,并构建了一个Integer数组:

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

7

这应该是单线的。

public String [] concatenate (final String array1[], final String array2[])
{
    return Stream.concat(Stream.of(array1), Stream.of(array2)).toArray(String[]::new);
}

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
..但是效率低下又缓慢。
JonasCz-恢复莫妮卡2015年

6

这可行,但是您需要插入自己的错误检查。

public class StringConcatenate {

    public static void main(String[] args){

        // Create two arrays to concatenate and one array to hold both
        String[] arr1 = new String[]{"s","t","r","i","n","g"};
        String[] arr2 = new String[]{"s","t","r","i","n","g"};
        String[] arrBoth = new String[arr1.length+arr2.length];

        // Copy elements from first array into first part of new array
        for(int i = 0; i < arr1.length; i++){
            arrBoth[i] = arr1[i];
        }

        // Copy elements from second array into last part of new array
        for(int j = arr1.length;j < arrBoth.length;j++){
            arrBoth[j] = arr2[j-arr1.length];
        }

        // Print result
        for(int k = 0; k < arrBoth.length; k++){
            System.out.print(arrBoth[k]);
        }

        // Additional line to make your terminal look better at completion!
        System.out.println();
    }
}

它可能不是最有效的,但是除了Java自己的API外,它不依赖任何其他东西。


2
+1。最好将第二个for循环替换为:for(int j = 0; j < arr2.length; j++){arrBoth[arr1.length+j] = arr2[j];}
bancer

使用String[] arrBoth = java.util.Arrays.copyOf(arr1, arr1.length + arr2.length)跳过第一个for循环。节省与大小成正比的时间arr1
约翰·迈耶

5

这是String数组的转换函数:

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 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类型相同,这将为您提供另一个包含两个数组的相同类型的数组。


出于性能原因,我将预先计算ArrayList的最终大小,因为根据定义,ArrayList会分配一个新数组,并在每次当前数组已满时复制其元素。否则,我会直接去链表不遭受这样的问题
USR-本地ΕΨΗΕΛΩΝ

5

使用高性能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;
}

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

这是我对Joachim Sauer的concatAll的稍加改进的版本。如果运行时可用,它可以使用Java 6的System.arraycopy在Java 5或6上运行。此方法(IMHO)非常适用于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和non-copyOf版本,而不是同时进行反射的版本。
rektide 2011年

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。但是我认为这有它自己的美丽。


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

一个简单的变体,可以连接多个数组:

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

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


15
不得不为所有不必要的List对象创建而投票。
Outlaw程序员
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.