当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在Java中连接两个数组?》经验,为你挑选了23个好方法。

我需要String在Java中连接两个数组.

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

最简单的方法是什么?



1> Antti Kissan..:

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

码:

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


如果回答这个问题,它是如何"作弊"的?当然,对于这种特定情况,具有额外的依赖性可能是过度的,但是在调用它存在时没有任何损害,特别是因为Apache Commons中有如此多的优秀功能.
我认为这是一个很好的答案.还提供了POJO解决方案,但如果OP已经在他们的程序中使用Apache Commons(完全可以考虑它的受欢迎程度),他可能仍然不知道这个解决方案.然后他不会"为这一种方法添加依赖项",但会更好地利用现有的库.
我同意,这并没有真正回答这个问题.高级库可能很棒,但如果您想学习一种有效的方法,那么您需要查看库方法正在使用的代码.此外,在许多情况下,您不能只是通过产品中的另一个库.
如果您总是担心不为单个方法添加库,则不会添加任何新库.鉴于Apache Commons中出现的优秀实用程序,我强烈建议在第一个用例出现时添加它.
使用apache commons永远不应该被称为"作弊"我质疑开发人员的理智是不必要的依赖.
OP要求解决问题的最简单方法.这确实是最简单的方法,但只能假设库已经存在,这在问题中没有提到.否则,复制和粘贴几行代码实际上要简单得多,而不是只复制一行代码,然后再添加一个单独的库到项目中.
@Outlaw程序员,我想大多数人宁愿选择最简单的方法.Java已经足够冗长了.
我正在使用commons-lang-2.4.jar.ArrayUtils中没有泛型版本的addAll().所以我必须明确地将返回的Object []强制转换为String [].

2> jeannicolas..:

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

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


以下行将打破通用部分:concatenate(new String [] {"1"},new Object [] {new Object()})

3> Joachim Saue..:

可以编写一个完全通用的版本,甚至可以扩展为连接任意数量的数组.这个版本需要Java 6,因为它们使用Arrays.copyOf()

两个版本都避免创建任何中间List对象,并用于System.arraycopy()确保尽可能快地复制大型数组.

对于两个数组,它看起来像这样:

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


如果用不同组件类型的数组调用这些函数,这种方法就会出现问题,例如`concat(ai,ad)`,其中`ai`是`Integer []`,'ad`是`Double [ ]`.(在这种情况下,类型参数``被编译器解析为`<?extends Number>`.由`Arrays.copyOf`创建的数组将具有第一个数组的组件类型,即`Integer `在这个例子中.当函数即将复制第二个数组时,将抛出一个`ArrayStoreException`.解决方案是有一个额外的`Class type`参数.
@djBO:对于原始类型的数组,你需要为每种类型重载:只需复制代码并用`byte`替换每个`T`(并丢失``).
我会把它添加到开头,只是为了防守.if(first == null){if(second == null){return null; } return second; } if(second == null){return first; }
@djBo:怎么样:`ByteBuffer buffer = ByteBuffer.allocate(array1.length + array2.length); buffer.put(数组1); buffer.put(数组2); return buffer.array();`

4> Vitalii Fedo..:

Java 8中的单线程:

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

要么:

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


这有多高效?
@Will Hardwick-Smith:不,你只需要选择正确的流类,例如,如果`a`和`b`是`int []`,使用`int [] both = IntStream.concat(Arrays.stream(a ),Arrays.stream(b)).toArray();`
值得一读:https://jaxenter.com/java-performance-tutorial-how-fast-are-the-java-8-streams-118830.html tl; dr - streams可以是高性能还是无效,这取决于什么你在做他们和问题的限制(这不总是答案吗?大声笑)
另外,如果*a*或*b*是基本类型的数组,它们的流将需要是`.boxed()`因此它们是`Stream`类型而不是例如`IntStream`,它们不能作为参数传递给`Stream.concat`.
@Supuhstar:速度可能不及`System.arrayCopy`。但也不是特别慢。您可能不得不在*真正*性能敏感的上下文中使用*巨大*数组多次*多次执行此操作,以使执行时间差异变得重要。

5> KARASZI Istv..:

或者与心爱的番石榴:

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)


什么是抽象问题?Dunno在这里重新发明轮子的重要性是什么,如果你想了解问题,请查看源代码或阅读它.专业代码应该使用高级库,如果它是在Google内部开发的话,会更好!
虽然使用库很好,但遗憾的是问题已经被抽象掉了.因此,潜在的解决方案仍然难以捉摸.

6> Fabian Steeg..:

使用Java API:

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


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

7> rghome..:

您可以将这两个数组附加到两行代码中.

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

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

您应该避免涉及ArrayLists,流等的解决方案,因为这些解决方案需要分配临时内存而没有用处.

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



8> 小智..:

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


虽然可能效率很低.

9> volley..:

我最近在内存轮换过多的情况下遇到了问题.如果已知a和/或b通常是空的,那么这是另一个silvertab代码的修改(也是通用的):

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

(在任何一种情况下,数组重用行为都应该是明确的JavaDoced!)


但是,这意味着您返回相同的数组并更改返回的数组上的值会更改返回的输入数组的相同位置的值.
调用者通常会期望调用concat()来返回新分配的数组.如果a或b为null,则concat()将返回传入其中的一个数组.这种重复使用可能是意料之外的.(是的,arraycopy只进行复制.重新使用来自直接返回a或b.)

10> Apocalisp..:

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

import static fj.data.Array.array;

...然后

Array both = array(first).append(array(second));

要取出展开的阵列,请致电

String[] s = both.array();



11> h-rai..:
ArrayList both = new ArrayList(Arrays.asList(first));
both.addAll(Arrays.asList(second));

both.toArray(new String[0]);


或者更好,没有不必要的零长度数组:`both.toArray(new String [both.size()])`;)
答案很好,但有点破碎.为了使它完美,你应该将toArray()传递给你需要的类型数组.在上面的示例中,代码应为:both.toArray(new String [0])请参阅:http://stackoverflow.com/questions/4042434/converting-arrayliststring-to-string-in-java

12> volley..:

这是对silvertab解决方案的改编,改进了仿制药:

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

注意:请参阅Joachim对Java 6解决方案的回答.它不仅消除了警告; 它也更短,更高效,更容易阅读!


如果使用Arrays.copyOf(),则可以消除未经检查的警告.请参阅我的答案以了解实施情况

13> 小智..:

Java8使用Stream的另一种方式

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



14> 小智..:

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

如果你想连接 String

用于连接两个String Array的示例代码

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

这是Main方法

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

        }
    }  

我们也可以用这种方式.



15> Reto Höhener..:

请原谅我在这个已经很久的列表中添加了另一个版本.我查看了每个答案,并决定我真的想要一个只有一个参数的签名版本.我还添加了一些参数检查,以便在意外输入的情况下通过合理的信息从早期故障中受益.

@SuppressWarnings("unchecked")
public static  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;
}



16> Paul..:

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

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



17> hpgisler..:

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

谢谢silvertab!

public class Array {

   public static  T[] concat(T[] a, T[] b, ArrayBuilderI 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 {

   public T[] build(int size);
}

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

public class IntegerArrayBuilder implements ArrayBuilderI {

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



18> keisar..:

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

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



19> glue..:

这有效,但您需要插入自己的错误检查.

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之外的任何东西.


+1.用以下方法替换第二个`for`循环会更好:`for(int j = 0; j
20> doles..:

哇!这里有很多复杂的答案,包括一些依赖外部依赖的简单答案.怎么样这样做:

String [] arg1 = new String{"a","b","c"};
String [] arg2 = new String{"x","y","z"};

ArrayList temp = new ArrayList();
temp.addAll(Arrays.asList(arg1));
temp.addAll(Arrays.asList(arg2));
String [] concatedArgs = temp.toArray(new String[arg1.length+arg2.length]);



21> 小智..:

这应该是单线的。

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



22> Oritm..:

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



23> Ephraim..:

怎么样简单

public static class Array {

    public static  T[] concat(T[]... arrays) {
        ArrayList al = new ArrayList();
        for (T[] one : arrays)
            Collections.addAll(al, one);
        return (T[]) al.toArray(arrays[0].clone());
    }
}

就这么做Array.concat(arr1, arr2).只要arr1arr2属于同一类型,这将为您提供包含两个数组的相同类型的另一个数组.

推荐阅读
mobiledu2402852357
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有