thinking in java 11——Arrays相关方法源码

System.arraycopy

.
1. 复制数组比for循环快的多,因为使用native本地方法实现的

//:Demo
int[] i = new int[7];
int[] j = new int[10];
Arrays.fill(i, 47);
Arrays.fill(j, 99);
System.out.println("i = "+Arrays.toString(i));
System.out.println("j = "+Arrays.toString(j));
System.arraycopy(i, 0, j, 0, i.length);
System.out.println("j = "+Arrays.toString(j));
/**:~
i = [47, 47, 47, 47, 47, 47, 47]
j = [99, 99, 99, 99, 99, 99, 99, 99, 99, 99]
j = [47, 47, 47, 47, 47, 47, 47, 99, 99, 99]
*/

//:source
public static native void arraycopy(Object src,  int  srcPos,Object dest, int destPos,int length);
/**
*可以复制基本类型数组或者对象数组,注:1.如果复制对象数组,那么只是
*复制了对象的引用——而不是对象本身的拷贝;2.System.arraycopy()
*不会执行自动包装和自动拆包,两个数组必须具有相同的确切类型
*/


Arrays

.
1. equals

//:Demo
int[] a1 = new int[10];
int[] a2 = new int[10];
Arrays.fill(a1, 47);
Arrays.fill(a2, 47);
System.out.println(Arrays.equals(a1, a2));

String[] s1 = new String[4];
Arrays.fill(s1, "hi");
String[] s2 = {new String("hi"),new String("hi"),new String("hi"),new String("hi")};
System.out.println(Arrays.equals(s1, s2));
/**:~
*true
*true
*/

//:source
/**
     * Returns <tt>true</tt> if the two specified arrays of ints are
     * <i>equal</i> to one another.  Two arrays are considered equal if both
     * arrays contain the same number of elements, and all corresponding pairs
     * of elements in the two arrays are equal.  In other words, two arrays
     * are equal if they contain the same elements in the same order.  Also,
     * two array references are considered equal if both are <tt>null</tt>.<p>
     *
     * @param a one array to be tested for equality
     * @param a2 the other array to be tested for equality
     * @return <tt>true</tt> if the two arrays are equal
     */
    public static boolean equals(int[] a, int[] a2) {
        if (a==a2)//指向地址相同返回true
            return true;
        if (a==null || a2==null)//鲁棒性
            return false;

        int length = a.length;
        if (a2.length != length)//长度不相等返回false
            return false;

        for (int i=0; i<length; i++)//遍历比对值
            if (a[i] != a2[i])
                return false;

        return true;
    }

/*===================================================*/

/**
     * Returns <tt>true</tt> if the two specified arrays of Objects are
     * <i>equal</i> to one another.  The two arrays are considered equal if
     * both arrays contain the same number of elements, and all corresponding
     * pairs of elements in the two arrays are equal.  Two objects <tt>e1</tt>
     * and <tt>e2</tt> are considered <i>equal</i> if <tt>(e1==null ? e2==null
     * : e1.equals(e2))</tt>.  In other words, the two arrays are equal if
     * they contain the same elements in the same order.  Also, two array
     * references are considered equal if both are <tt>null</tt>.<p>
     *
     * @param a one array to be tested for equality
     * @param a2 the other array to be tested for equality
     * @return <tt>true</tt> if the two arrays are equal
     */
    public static boolean equals(Object[] a, Object[] a2) {
        if (a==a2)//地址相同返回true
            return true;
        if (a==null || a2==null)//鲁棒性
            return false;

        int length = a.length;
        if (a2.length != length)//判断长度
            return false;

        for (int i=0; i<length; i++) {//遍历比对值
            Object o1 = a[i];
            Object o2 = a2[i];
            //鲁棒性
            if (!(o1==null ? o2==null : o1.equals(o2)))
                return false;
        }

        return true;
    }

.
2. public static void fill():重载了多种类型

//:Demo
int[] i = new int[7];
Arrays.fill(i, 47);
System.out.println(Arrays.toString(i));
///~[47, 47, 47, 47, 47, 47, 47]

//:source(以int[]为例)
/**
     * Assigns the specified int value to each element of the specified array
     * of ints.
     *
     * @param a the array to be filled
     * @param val the value to be stored in all elements of the array
     */
public static void fill(int[] a, int val) {
        for (int i = 0, len = a.length; i < len; i++)
            a[i] = val;
}
/**
     * Assigns the specified long value to each element of the specified
     * range of the specified array of longs.  The range to be filled
     * extends from index <tt>fromIndex</tt>, inclusive, to index
     * <tt>toIndex</tt>, exclusive.  (If <tt>fromIndex==toIndex</tt>, the
     * range to be filled is empty.)
     *
     * @param a the array to be filled
     * @param fromIndex the index of the first element (inclusive) to be
     *        filled with the specified value
     * @param toIndex the index of the last element (exclusive) to be
     *        filled with the specified value
     * @param val the value to be stored in all elements of the array
     * @throws IllegalArgumentException if <tt>fromIndex &gt; toIndex</tt>
     * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex &lt; 0</tt> or
     *         <tt>toIndex &gt; a.length</tt>
     */
public static void fill(long[] a, int fromIndex, int toIndex, long val) {
        rangeCheck(a.length, fromIndex, toIndex);
        for (int i = fromIndex; i < toIndex; i++)
            a[i] = val;
}
/**
     * Checks that {@code fromIndex} and {@code toIndex} are in
     * the range and throws an appropriate exception, if they aren't.
     */
private static void rangeCheck(int length, int fromIndex, int toIndex) {
        if (fromIndex > toIndex) {
            throw new IllegalArgumentException(
                "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
        }
        if (fromIndex < 0) {
            throw new ArrayIndexOutOfBoundsException(fromIndex);
        }
        if (toIndex > length) {
            throw new ArrayIndexOutOfBoundsException(toIndex);
        }
}
/**
*可以看到fill方法实现很简单,就是循环复制,一般这个方法很少用,
*用在生成测试数据有点用
*/

.
3. sort:策略模式

//:Demo
int[] a = {2,4,1,5,7,0,9,8};
Arrays.sort(a);
System.out.println(Arrays.toString(a));
///:~[0, 1, 2, 4, 5, 7, 8, 9]
//:source (int[])
public static void sort(int[] a) {
        DualPivotQuicksort.sort(a);//快排
}

/**
 *Sorts the specified array.
 *
 * @param a the array to be sorted
 */
public static void sort(int[] a) {
    sort(a, 0, a.length - 1);//排序
}

/**
     * Sorts the specified range of the array.
     *
     * @param a the array to be sorted
     * @param left the index of the first element, inclusive, to be sorted
     * @param right the index of the last element, inclusive, to be sorted
     */
/*================================================
快排思想:选取分割点t,将小于t和大于t的分别分在两端,然后按照相同的思想递归排下去,最后将排序好的小数组合并,详见博文快排
=================================================*/
public static void sort(int[] a, int left, int right) {
    // Use Quicksort on small arrays(length < 286)
 if (right - left < QUICKSORT_THRESHOLD) {//小数组用快排
      sort(a, left, right, true);//源代码太过于长,可自行查看DualPivotQuicksort
      return;
  }
 /*
  * Index run[i] is the start of i-th run
  * (ascending or descending sequence).
  */
 int[] run = new int[MAX_RUN_COUNT + 1];
 int count = 0; run[0] = left;//初始取a[left]为分割点

 // Check if the array is nearly sorted:最多轮询68次
 for (int k = left; k < right; run[count] = k) {
     if (a[k] < a[k + 1]) { // ascending
         while (++k <= right && a[k - 1] <= a[k]);
     } else if (a[k] > a[k + 1]) { // descending
         while (++k <= right && a[k - 1] >= a[k]);
         for (int lo=run[count]-1,hi=k;++lo<--hi;){//变换递增
             int t=a[lo];a[lo] = a[hi]; a[hi] = t;
         }
     } else { // equal
         for (int m = MAX_RUN_LENGTH; ++k <= right && a[k - 1] == a[k]; ) {//超过33个数相等则直接DualPivotQuicksort
             if (--m == 0) {
                 sort(a, left, right, true);
                 return;
             }
         }
     }

     /*
      * The array is not highly structured,
      * use Quicksort instead of merge sort.
      */
     if (++count == MAX_RUN_COUNT) {
         sort(a, left, right, true);
         return;
     }
 }

 // Check special cases
 if (run[count] == right++) { // The last run contains one element
     run[++count] = right;
 } else if (count == 1) { // The array is already sorted:已经有序
     return;
 }

 /*
  * Create temporary array, which is used for merging.
  * Implementation note: variable "right" is increased by 1.
  */
 int[] b; byte odd = 0;
 for (int n = 1; (n <<= 1) < count; odd ^= 1);

 if (odd == 0) {
     b = a; a = new int[b.length];
     for (int i = left - 1; ++i < right; a[i] = b[i]);
 } else {
     b = new int[a.length];
 }

 // Merging
 for (int last; count > 1; count = last) {
     for (int k = (last = 0) + 2; k <= count; k += 2) {
         int hi = run[k], mi = run[k - 1];
         for (int i = run[k - 2], p = i, q = mi; i < hi; ++i) {
             if (q >= hi || p < mi && a[p] <= a[q]) {
                 b[i] = a[p++];
             } else {
                 b[i] = a[q++];
             }
         }
         run[++last] = hi;
     }
     if ((count & 1) != 0) {
         for (int i = right, lo = run[count - 1]; --i >= lo;
             b[i] = a[i]
         );
         run[++last] = right;
     }
     int[] t = a; a = b; b = t;
 }
}

/*===================================================*/

/**排序是依赖于比较进行的,一般对象实现比较需要实现Comparable<T>
*接口,也可以实现comparator接口,前面章节会有关于这两个接口的介绍
*/
//:source
public static void sort(Object[] a) {
        if (LegacyMergeSort.userRequested)
            legacyMergeSort(a);
        else
            ComparableTimSort.sort(a);
}

/** To be removed in a future release. */
private static void legacyMergeSort(Object[] a) {
    Object[] aux = a.clone();
    mergeSort(aux, a, 0, a.length, 0);//归并排序
}

/*====================================================
归并排序思想:分治法
=====================================================*/
private static void mergeSort(Object[] src,
                                  Object[] dest,
                                  int low,
                                  int high,
                                  int off) {
        int length = high - low;

        // Insertion sort on smallest arrays
        if (length < INSERTIONSORT_THRESHOLD) {
            for (int i=low; i<high; i++)
                for (int j=i; j>low &&
                         ((Comparable) dest[j-1]).compareTo(dest[j])>0; j--)
                    swap(dest, j, j-1);
            return;
        }

        // Recursively sort halves of dest into src
        int destLow  = low;
        int destHigh = high;
        low  += off;
        high += off;
        int mid = (low + high) >>> 1;
        mergeSort(dest, src, low, mid, -off);
        mergeSort(dest, src, mid, high, -off);

        // If list is already sorted, just copy from src to dest.  This is an
        // optimization that results in faster sorts for nearly ordered lists.
        if (((Comparable)src[mid-1]).compareTo(src[mid]) <= 0) {
            System.arraycopy(src, low, dest, destLow, length);
            return;
        }

        // Merge sorted halves (now in src) into dest
        for(int i = destLow, p = low, q = mid; i < destHigh; i++) {
            if (q >= high || p < mid && ((Comparable)src[p]).compareTo(src[q])<=0)
                dest[i] = src[p++];
            else
                dest[i] = src[q++];
        }
    }
/*=================ComparableTimSort=================*/
/*
     * The next two methods (which are package private and static) constitute
     * the entire API of this class.  Each of these methods obeys the contract
     * of the public method with the same signature in java.util.Arrays.
     */
static void sort(Object[] a) {//ComparableTimSort
          sort(a, 0, a.length);
}
static void sort(Object[] a, int lo, int hi) {
        rangeCheck(a.length, lo, hi);
        int nRemaining  = hi - lo;
        if (nRemaining < 2)
            return;  // Arrays of size 0 and 1 are always sorted

        // If array is small, do a "mini-TimSort" with no merges
        if (nRemaining < MIN_MERGE) {
            int initRunLen = countRunAndMakeAscending(a, lo, hi);
            binarySort(a, lo, hi, lo + initRunLen);
            return;
        }
/*===================================================
二分排序:折半插入排序
===================================================*/
@SuppressWarnings("fallthrough")
    private static void binarySort(Object[] a, int lo, int hi, int start) {
        assert lo <= start && start <= hi;
        if (start == lo)
            start++;
        for ( ; start < hi; start++) {
            @SuppressWarnings("unchecked")
            Comparable<Object> pivot = (Comparable) a[start];

            // Set left (and right) to the index where a[start] (pivot) belongs
            int left = lo;
            int right = start;
            assert left <= right;
            /*
             * Invariants:
             *   pivot >= all in [lo, left).
             *   pivot <  all in [right, start).
             */
            while (left < right) {
                int mid = (left + right) >>> 1;
                if (pivot.compareTo(a[mid]) < 0)
                    right = mid;
                else
                    left = mid + 1;
            }
            assert left == right;

            /*
             * The invariants still hold: pivot >= all in [lo, left) and
             * pivot < all in [left, start), so pivot belongs at left.  Note
             * that if there are elements equal to pivot, left points to the
             * first slot after them -- that's why this sort is stable.
             * Slide elements over to make room for pivot.
             */
            int n = start - left;  // The number of elements to move
            // Switch is just an optimization for arraycopy in default case
            switch (n) {
                case 2:  a[left + 2] = a[left + 1];
                case 1:  a[left + 1] = a[left];
                         break;
                default: System.arraycopy(a, left, a, left + 1, n);
            }
            a[left] = pivot;
        }
    }

.
4. binarySearch

//:Demo
int[] a1 = {2,4,1,5,7,0,9,8};
Arrays.sort(a1);
System.out.println(Arrays.toString(a1));
System.out.println(Arrays.binarySearch(a1,3));
///:~找到时返回位置index,未找到返回返回值 = -(插入点)-1
/**
*[0, 1, 2, 4, 5, 7, 8, 9]
*-4
*/

//:Source
public static int binarySearch(int[] a, int key) {
    return binarySearch0(a, 0, a.length, key);
}

 // Like public version, but without range checks.
    private static int binarySearch0(int[] a, int fromIndex, int toIndex,int key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {//当未找到时一直折半下去
            int mid = (low + high) >>> 1;//无符号右移
            int midVal = a[mid];

            if (midVal < key)
                low = mid + 1;
            else if (midVal > key)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.***
    }
/*=================================================*/
    public static int binarySearch(Object[] a, Object key) {
        return binarySearch0(a, 0, a.length, key);
    }
// Like public version, but without range checks.
    private static int binarySearch0(Object[] a, int fromIndex, int toIndex, Object key) {
        int low = fromIndex;
        int high = toIndex - 1;

        while (low <= high) {
            int mid = (low + high) >>> 1;
            /*需要实现comparable接口,当使用comparator时需要作为参数穿进去,可以自行查阅源码*/
            Comparable midVal = (Comparable)a[mid];
            int cmp = midVal.compareTo(key);

            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found.
    }

未完待续~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值