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。

不足之處,請在下面留言。謝謝大家堅持到現在,作爲程序猿的不易。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章