Java中五种方法实现数组的合并,源码详解

Java中的数组合并,常见有五种实现方式:


  1. 使用JDK自带的System.arraycopy()方法。
  2. 使用apache的commons-lang3包下的ArrayUtils.addAll(a,b)方法。
  3. 手把手带你写自己的array_utils.arraymergn()方法

  3.1 最基础的,新建一个新的数组,将需要合并的数组值添加进去。固定长度

  3.2 多参实现多数组合并

  3.3 泛型实现数组合并(重点)

下面对每个方法,进行详细的介绍。不会按照顺序,依照难易程度介绍:

方法1 2 3 循序渐进,时间紧的直接看 方法 4 5


1、JDK自带的方法。

    /* 
     * Copies an array from the specified source array, beginning at the
     * specified position, to the specified position of the destination array.
     * @param      src      the source array.
     * @param      srcPos   starting position in the source array.
     * @param      dest     the destination array.
     * @param      destPos  starting position in the destination data.
     * @param      length   the number of array elements to be copied.
     * @exception  IndexOutOfBoundsException  if copying would cause
     *               access of data outside array bounds.
     * @exception  ArrayStoreException  if an element in the <code>src</code>
     *               array could not be stored into the <code>dest</code> array
     *               because of a type mismatch.
     * @exception  NullPointerException if either <code>src</code> or
     *               <code>dest</code> is <code>null</code>.
     */
    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

看完源码就是将源数组(src)起始位置(srcPos)开始将长度(length)的元素复制到目标数组(dest),目标数组从指定位置(destPos)位置开始接收复制元素。

System.arraycopy()实现,该方法被 native修饰,无法看到底层,但是可以分析其实就是我们最常用的新建目标数组往里面塞东西。

2、个人觉得最简单也是最常用的方法。虽然low点

 public int[] AddArray1(int[] a, int[] b, int[] c, int[] d) {
        int[] Result = new int[a.length + b.length + c.length + d.length];
        for (int i = 0; i < a.length; i++) {
            Result[i] = a[i];
        }
        for (int i = 0; i < b.length; i++) {
            Result[i + a.length] = b[i];
        }
        for (int i = 0; i < c.length; i++) {
            Result[i + a.length + b.length] = c[i];
        }
        for (int i = 0; i < d.length; i++) {
            Result[i + a.length + b.length + c.length] = d[i];
        }
        return Result;
    }

 @Test
    public void test() {
        int[] a = {1, 2, 3};
        int[] b = {4, 5, 6};
        int[] c = {7, 8, 9};
        int[] d = {10, 11, 12};

        int[] Result1;
        Result1 = AddArray1(a, b, c, d);
        for (int i : Result1) {
            System.out.print(i + " ");
        }
        System.out.println("----------");
}

为了举个列子,写了一堆重复代码,依次for循环,Result接受其实就是JDK中的destPost的位置。

@Test 作者建的是Maven工程,单元测试框架,写一个main,必须用static声明,方法都得是static,显得超级low。

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
</dependency>

3、在方法2的步骤上,考虑到如果数组的个数不确定怎么办。

     使用 ...  JDK8带的多参数判断,很多人喜欢用Java的反射机制来获取类中方法名中的参数。

我觉得还是使用JavaScript操作方法参数的方式,简单 通俗

 public int[] AddArray2(int[]... categorys) {
        int size = categorys.length;  //获取参数个数
        int length = 0;
        for (int i = 0; i < size; i++) {
            length += categorys[i].length;  //每个数组的长度
        }
        int index = 0;
        int[] Result = new int[length];
        for (int i = 0; i < size; i++) {
            for (int j = 0; j < categorys[i].length; j++) {
                Result[index] = categorys[i][j];
                index++;
            }
        }
        return Result;
    }

上面3个方法,学过Java的都会,我其实也不好意思写出来,但是没办法,照顾新人,有教无类。


4、使用Apache的common-lang3.jar包,随便大家下载jar还是添加maven依赖,这不是重点

<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-lang3</artifactId>
    <version>3.5</version>
</dependency>

使用ArrayUtils.addAll(a,b); a b 数据类型必须一致

分析源码:

源码有点长,

      1、官方提供的几种方法。

       ArrayUtils.addAll(null, null)     = null
     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
     * ArrayUtils.addAll([], [])         = []
     * ArrayUtils.addAll([null], [null]) = [null, null]
     * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]。

    2、当数组中有null的时候,使用浅克隆。(深浅克隆,可以参考后期推出的设计模块)

          利用Java反射机制获取参数类型和参数数量,和泛型参数。

          最后还是使用arraycopy的方法。

    3、其实多参数方法3中已经介绍了,泛型实现在方法5中具体介绍。

/**
     * <p>Adds all the elements of the given arrays into a new array.
     * <p>The new array contains all of the element of {@code array1} followed
     * by all of the elements {@code array2}. When an array is returned, it is always
     * a new array.
     *
     * <pre>
     * ArrayUtils.addAll(null, null)     = null
     * ArrayUtils.addAll(array1, null)   = cloned copy of array1
     * ArrayUtils.addAll(null, array2)   = cloned copy of array2
     * ArrayUtils.addAll([], [])         = []
     * ArrayUtils.addAll([null], [null]) = [null, null]
     * ArrayUtils.addAll(["a", "b", "c"], ["1", "2", "3"]) = ["a", "b", "c", "1", "2", "3"]
     * </pre>
     *
     * @param <T> the component type of the array
     * @param array1  the first array whose elements are added to the new array, may be {@code null}
     * @param array2  the second array whose elements are added to the new array, may be {@code null}
     * @return The new array, {@code null} if both arrays are {@code null}.
     *      The type of the new array is the type of the first array,
     *      unless the first array is null, in which case the type is the same as the second array.
     * @since 2.1
     * @throws IllegalArgumentException if the array types are incompatible
     */
    public static <T> T[] addAll(final T[] array1, final T... array2) {
        if (array1 == null) {
            return clone(array2);
        } else if (array2 == null) {
            return clone(array1);
        }
        final Class<?> type1 = array1.getClass().getComponentType();
        @SuppressWarnings("unchecked") // OK, because array is of type T
        final
        T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
        System.arraycopy(array1, 0, joinedArray, 0, array1.length);
        try {
            System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
        } catch (final ArrayStoreException ase) {
            // Check if problem was due to incompatible types
            /*
             * We do this here, rather than before the copy because:
             * - it would be a wasted check most of the time
             * - safer, in case check turns out to be too strict
             */
            final Class<?> type2 = array2.getClass().getComponentType();
            if (!type1.isAssignableFrom(type2)) {
                throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
                        + type1.getName(), ase);
            }
            throw ase; // No, so rethrow original
        }
        return joinedArray;
    }

官方提供的实现方法:快速重载


方法5:获取泛型数组

上面的Java中方法多参数操作,已经懵了,泛型会更懵了,学习Java的实现,很多老师都会手把手实现List,Map,其中就是用到了泛型,接下里介绍,利用泛型实现自定义类型(数组)。

1、首先定义接口

public interface GeneratorT<T> {
    public T getAll();
}

对就是这么简单,然后实现接口就完事了

2、接口实现

 class DcT implements GeneratorT {
        private Object[] array;

        public DcT(int size) {
            array = new Object[size];
        }

        public void put(int index, Object item) {
            array[index] = item;
        }

        @Override
        public Object[] getAll() {
            return array;
        }
    }

   Dc就是作者的名字了,T表示泛型,类名DcT没什么含义,该类主要的功能的是:

        构造器输入数组的大小,put(index,item);往数组index的位置放入item。

        @override getAll()  就是获取数组值。

3、测试

        double[] a1 = {1.0, 2.0, 3.0};
        double[] a2 = {4.0, 5.0, 6.0};
        DcT t = new DcT(a1.length);
        for (int i = 0; i < a1.length; i++) {
            t.put(i, a1[i]);
        }
        Object[] all = t.getAll();
        for (int i = 0; i <all.length ; i++) {
            System.out.println(all[i]);  //输出结果
        }

方法5已经获取了单个数组的值(随你什么类型的数组),接下来就是数组的合并了(上面介绍了4种方法),方法5实现了不同类型的数组只需要一个函数就可以进行合并。

将输入类型提升到了Object好处是接受多种类型,坏处是可以进行不同类型数组的合并,将方法3改成泛型的形式,实现不同类型数组的合并(并没有实际的意思纯粹是为了好玩,代码就不贴了,没有实际意义)。方法是将变量值全部变成了String。

不足之处,请在下面留言。谢谢大家坚持到现在,作为程序猿的不易。

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值