<form id="dlljd"></form>
        <address id="dlljd"><address id="dlljd"><listing id="dlljd"></listing></address></address>

        <em id="dlljd"><form id="dlljd"></form></em>

          <address id="dlljd"></address>
            <noframes id="dlljd">

              聯系我們 - 廣告服務 - 聯系電話:
              您的當前位置: > 關注 > > 正文

              構造器必須是私有的 工具類的特征是什么?

              來源:CSDN 時間:2023-02-03 15:10:09

              工具類特征:

              構造器必須是私有的,工具類一般不需要初始化,可以直接使用;工具類的方法必須是被static final方法修飾,保證方法不可變;不要在工具類方法中對共享變量有修改的操作,如果一定要有,必須加鎖保證線程安全;工具類的所有方法都沒有線程安全問題;


              (資料圖片僅供參考)

              一、Arrays

              Arrays主要提供了對數組的高效操作,包括排序、查找、填充、拷貝、相等判斷等操作;

              1、sort(int[] a)

              1.1、JDK1.6

              1.1.1、源碼

              // int類型數組排序public static void sort(int[] a) {sort1(a, 0, a.length);}private static void sort1(int x[], int off, int len) {// Insertion sort on smallest arrays    if (len < 7) {for (int i = off; i < len + off; i++)            for (int j = i; j > off && x[j - 1] > x[j]; j--)                swap(x, j, j - 1);        return;    }    // Choose a partition element, v    int m = off + (len >> 1);       // Small arrays, middle element    if (len > 7) {int l = off;        int n = off + len - 1;        if (len > 40) {// Big arrays, pseudomedian of 9            int s = len / 8;            l = med3(x, l, l + s, l + 2 * s);            m = med3(x, m - s, m, m + s);            n = med3(x, n - 2 * s, n - s, n);        }        m = med3(x, l, m, n); // Mid-size, med of 3    }    int v = x[m];    // Establish Invariant: v* (v)* v*    int a = off, b = a, c = off + len - 1, d = c;    while (true) {while (b <= c && x[b] <= if="" while="" c="">= b && x[c] >= v) {if (x[c] == v)                swap(x, c, d--);            c--;        }        if (b > c)            break;        swap(x, b++, c--);    }    // Swap partition elements back to middle    int s, n = off + len;    s = Math.min(a - off, b - a);    vecswap(x, off, b - s, s);    s = Math.min(d - c, n - d - 1);    vecswap(x, b, n - s, s);    // Recursively sort non-partition-elements    if ((s = b - a) > 1)        sort1(x, off, s);    if ((s = d - c) > 1)        sort1(x, n - s, s);}/** * Swaps x[a] with x[b]. */private static void swap(int x[], int a, int b) {int t = x[a];    x[a] = x[b];    x[b] = t;}/** * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)]. */private static void vecswap(int x[], int a, int b, int n) {for (int i = 0; i < n; i++, a++, b++)        swap(x, a, b);}/** * Returns the index of the median of the three indexed integers. */private static int med3(int x[], int a, int b, int c) {return (x[a] < x[b] ?            (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :            (x[b] > x[c] ? b : x[a] > x[c] ? c : a));}

              1.1.2、分析

              (1)數組長度小于7,那么排序時基于基本的插入排序算法(2)數組長度大于7,那么在使用的優化后的快速排序,對應數組長度在7和40之間的數組,取的切分元素相對來說簡單點

              1.2、JDK1.7

              1.2.1、源碼:

              public static void sort(int[] a) {DualPivotQuicksort.sort(a);}// 下面方法來自:java.util.DualPivotQuicksort#sort(int[])public static void sort(int[] a) {sort(a, 0, a.length - 1);}/** * If the length of an array to be sorted is less than this * constant, Quicksort is used in preference to merge sort. */private static final int QUICKSORT_THRESHOLD = 286;/** * The maximum number of runs in merge sort. */private static final int MAX_RUN_COUNT = 67;/** * The maximum length of run in merge sort. */private static final int MAX_RUN_LENGTH = 33;public static void sort(int[] a, int left, int right) {// Use Quicksort on small arrays    if (right - left < QUICKSORT_THRESHOLD) {sort(a, left, right, true);        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;    // Check if the array is nearly sorted    for (int k = left; k < right; run[count] = k) {if (a[k] < a[k + 1]) {// ascending            while (++k <= right && a[k - 1] <= else="" if=""> a[k + 1]) {// descending            while (++k < = right="" k="" -="">= 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]; ) {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] <= else="" if="" count="" for="" int="" i="right," lo="run[count" -="" --i="">= lo;                 b[i] = a[i]                    );            run[++last] = right;        }        int[] t = a; a = b; b = t;    }}/** * Sorts the specified range of the array by Dual-Pivot Quicksort. * * @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 * @param leftmost indicates if this part is the leftmost in the range */private static void sort(int[] a, int left, int right, boolean leftmost){}

              在JDK7中,排序使用的雙軸快速排序,其要比傳統的單軸排序要快

              雙軸快速排序:如果數組的長度小于QUICKSORT_THRESHOLD的話就會使用這個雙軸快速排序,而這個值是286

              if (right - left < QUICKSORT_THRESHOLD) {sort(a, left, right, true);    return;}

              1.3、JDK1.8

              1.3.1、源碼

              public static void sort(int[] a) {DualPivotQuicksort.sort(a, 0, a.length - 1, null, 0, 0);}

              DualPivotQuicksort.sort方法

              private static final int QUICKSORT_THRESHOLD = 286;static void sort(int[] a, int left, int right,                 int[] work, int workBase, int workLen) {// Use Quicksort on small arrays,QUICKSORT_THRESHOLD為286,當要排序區間小于286時,發現調用了本類的重載sort方法    if (right - left < QUICKSORT_THRESHOLD) {sort(a, left, right, true);        return;    }    /**    * run[i] 意味著第i個有序數列開始的位置,(升序或者降序)    **/    int[] run =new int[MAX_RUN_COUNT + 1];    int count=0; run[0] = left;    // 檢查數組是不是已經接近有序狀態    for(int k = left; k < right; run[count] = k) {if(a[k] < a[k + 1]){// 升序            while(++k <= right && a[k - 1] <= else=""> a[k + 1]) {// 降序            while(++k <=right k="" -="">= a[k]);            //如果是降序的,找出k之后,把數列倒置            for (int lo = run[count],hi = k;++lo < --hi) {int t = a[lo]; a[lo] = a[hi]; a[hi] = t;            }        } else {// 相等            for(int m = MAX_RUN_LENGTH; ++k <=right && a[k - 1] == a[k];) {// 數列中有至少MAX_RUN_LENGTH的數據相等的時候,直接使用快排。                // 這里為什么這么處理呢?                if(--m == 0){sort(a, left, right, true);                    return;                }            }        }        /**        * 數組并非高度有序,使用快速排序,因為數組中有序數列的個數超過了MAX_RUN_COUNT        */        if(++count == MAX_RUN_COUNT) {sort(a, left, right, true);            return;        }    }    //檢查特殊情況    if(run[count] == right++){// 最后一個有序數列只有最后一個元素        run[++count] =right; // 那給最后一個元素的后面加一個哨兵    } else if(count == 1) {// 整個數組中只有一個有序數列,說明數組已經有序啦,不需要排序了        return;    }    /**    * 創建合并用的臨時數組。    * 注意: 這里變量right被加了1,它在數列最后一個元素位置+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];    }    // 合并    // 最外層循環,直到count為1,也就是棧中待合并的序列只有一個的時候,標志合并成功    // a 做原始數組,b 做目標數組    for(int last; count > 1; count = last) {// 遍歷數組,合并相鄰的兩個升序序列        for(int k = (last = 0) + 2; k <= count; k += 2) {// 合并run[k-2] 與 run[k-1]兩個序列            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] < = else="" count="" int="" i="right," lo="run[count" --i="">= lo; b[i] = a[i]);            run[++last] = right;        }        //臨時數組,與原始數組對調,保持a做原始數組,b 做目標數組        int[] t = a; a = b; b = t;    }}int length = right - left + 1;// INSERTION_SORT_THRESHOLD為47,發現當要排序的個數小于47個時,采用插入排序,采用了哨兵方法,對于新元素從他前一個一個一個比較// Use insertion sort on tiny arraysif (length < INSERTION_SORT_THRESHOLD) {if (leftmost) {/*        * Traditional (without sentinel) insertion sort,        * optimized for server VM, is used in case of        * the leftmost part.        */        for (int i = left, j = i; i < right; j = ++i) {int ai = a[i + 1];            while (ai < a[j]) {a[j + 1] = a[j];                if (j-- == left) {break;                }            }            a[j + 1] = ai;        }    } else {/**        * 首先跨過開頭的升序的部分        */        do {if(left > right) {return;            }        }while(a[++left] >= a[left - 1]);        /**        * 這里用到了成對插入排序方法,它比簡單的插入排序算法效率要高一些        * 因為這個分支執行的條件是左邊是有元素的        * 所以可以直接從left開始往前查找。        */        for(int k = left; ++left <= k="++left)" int="" a1="" a2="a[left];">=a2            if(a1 < a2) {a2 = a1; a1 = a[left];            }            //先把兩個數字中較大的那個移動到合適的位置            while(a1 < a[--k]) {a[k + 2] = a[k]; //這里每次需要向左移動兩個元素            }            a[++k + 1] = a1;            //再把兩個數字中較小的那個移動到合適的位置            while(a2 < a[--k]) {a[k + 1] = a[k]; //這里每次需要向左移動一個元素            }            a[k + 1] = a2;        }        int last = a[right];        while(last < a[--right]) {a[right + 1] = last;        }        a[right + 1] = last;    }    return;}

              至于大過INSERTION_SORT_THRESHOLD(47)的,用一種快速排序(雙軸快排)的方法:

              從數列中挑出五個元素,稱為 “基準”(pivot);重新排序數列,所有元素比基準值小的擺放在基準前面,所有元素比基準值大的擺在基準的后面(相同的數可以到任一邊)。在這個分區退出之后,該基準就處于數列的中間位置。這個稱為分區(partition)操作;遞歸地(recursive)把小于基準值元素的子數列和大于基準值元素的子數列排序。

              總結:插入排序,快速排序,歸并排序三種排序的組合

              1.4、parallelSort

              并行排序,JDK1.8增加的新方法

              // 并行排序的最小數組長度private static final int MIN_ARRAY_SORT_GRAN = 1 << 13;public static void parallelSort(int[] a) {int n = a.length, p, g;    // 如果數據的長度小于 MIN_ARRAY_SORT_GRAN(1 << 13)    if (n <= MIN_ARRAY_SORT_GRAN ||        // 或者當前并行度級別是 1的話,仍然使用常規的雙軸快速排序        (p = ForkJoinPool.getCommonPoolParallelism()) == 1)        DualPivotQuicksort.sort(a, 0, n - 1, null, 0, 0);    else        // 否則使用并行排序        new ArraysParallelSortHelpers.FJInt.Sorter            (null, a, new int[n], 0, n, 0,                ((g = n / (p << 2)) <= MIN_ARRAY_SORT_GRAN) ?                MIN_ARRAY_SORT_GRAN : g).invoke();}

              2、搜索:binarySearch

              主要用于快速從數組中查找對應的值,如果查找到了,返回的是對應數組的下標的值;如果查詢不到則返回負數;

              二分查找確保數組一定是有序的,否則可能找不到對應的數據

              但是該方法有有一個問題:如果一個數組當中有多個元素,其無法保證匹配的到底是哪一個

              // a:我們要搜索的數組,fromIndex:從那里開始搜索,默認是0; toIndex:搜索到何時停止,默認是數組大小// key:我們需要搜索的值 // c:外部比較器private staticint binarySearch0(T[] a, int fromIndex, int toIndex,                                     T key, Comparator c) {// 如果比較器 c 是空的,直接使用 key 的 Comparable.compareTo 方法進行排序    // 假設 key 類型是 String 類型,String 默認實現了 Comparable 接口,就可以直接使用 compareTo 方法進行排序    if (c == null) {// 這是另外一個方法,使用內部排序器進行比較的方法        return binarySearch0(a, fromIndex, toIndex, key);    }    int low = fromIndex;    int high = toIndex - 1;    // 開始位置小于結束位置,就會一直循環搜索    while (low <= low="0,high" mid="(low" int="">>> 1;        T midVal = a[mid];        // 比較數組中間值和給定的值的大小關系        int cmp = c.compare(midVal, 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.}

              3、數據拷貝:copyOf和copyRange

              拷貝整個數組:copyOf

              public static int[] copyOf(int[] original, int newLength) {    int[] copy = new int[newLength];    System.arraycopy(original, 0, copy, 0,                        Math.min(original.length, newLength));    return copy;}

              拷貝部分數組:copyOfRange

              // original 原始數組數據// from 拷貝起點// to 拷貝終點public static char[] copyOfRange(char[] original, int from, int to) {// 需要拷貝的長度    int newLength = to - from;    if (newLength < 0)        throw new IllegalArgumentException(from + " > " + to);    // 初始化新數組    char[] copy = new char[newLength];    // 調用 native 方法進行拷貝,參數的意思分別是:    // 被拷貝的數組、從數組那里開始、目標數組、從目的數組那里開始拷貝、拷貝的長度    System.arraycopy(original, from, copy, 0,                    Math.min(original.length - from, newLength));    return copy;}

              基本上調用的是System.arrayCopy方法。

              另外在在ArrayList的toArray方法中,其調用的也是Arrays里的copyOf方法,因為ArrayList的底層實現是數組;

              4、數組填充:fill

              5、數組轉換為結婚:asList

              public staticListasList(T... a) {    return new ArrayList<>(a);}

              該方法有以下需要注意的:

              其返回的集合不是java.util.ArrayList的實例,而是Array的內部類:java.util.Arrays.ArrayList;java.util.Arrays.ArrayList不能對集合進行增、刪操作,其沒有實現AbstractList類中的add、remove方法;常見使用方法是:Listlist = new ArrayList<>(Arrays.asList(T...a));,可以將其作為參數傳到對應集合的構造方法里面;

              二、Collections

              為方便集合操作而產生的工具類。

              Collections也提供sort和binarySearch方法,其sort方法底層調用就是Arrays.sort方法,而binarySearch底層重寫了二分查找算法,實現邏輯和Arrays的二分查找算法一致

              1、sort()方法實現

              public staticvoid sort(Listlist)

              1.1、JDK1.6

              1.1.1、源碼

              // 基本方法public staticvoid sort(Listlist) {Object[] a = list.toArray();    Arrays.sort(a);    ListIteratori = list.listIterator();    for (int j=0; j<A.LENGTH; j++)="" {i.next();        i.set((T)a[j]);    }}/**********************下面方法未自Arrays***********************/// 調用 Arrays.sort(Object[] a) 排序方法,This algorithm offers guaranteed n*log(n) performance.public static void sort(Object[] a) {Object[] aux = (Object[])a.clone();    mergeSort(aux, a, 0, a.length, 0);}/** * Tuning parameter: list size at or below which insertion sort will be * used in preference to mergesort or quicksort. */private static final int INSERTIONSORT_THRESHOLD = 7;/** * Src is the source array that starts at index 0 * Dest is the (possibly larger) array destination with a possible offset * low is the index in dest to start sorting * high is the end index in dest to end sorting * off is the offset to generate corresponding low, high in src */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++];    }}private static void swap(Object[] x, int a, int b) {Object t = x[a];    x[a] = x[b];    x[b] = t;}

              1.2、JDK1.7

              1.2.1、源碼

              public staticvoid sort(Listlist) {Object[] a = list.toArray();    Arrays.sort(a);    ListIteratori = list.listIterator();    for (int j=0; j<A.LENGTH; j++)="" {i.next();        i.set((T)a[j]);    }}//Arrays.sort方法public static void sort(Object[] a) {if (LegacyMergeSort.userRequested)        legacyMergeSort(a);    else        ComparableTimSort.sort(a);}static final class LegacyMergeSort {private static final boolean userRequested =        java.security.AccessController.doPrivileged(            new sun.security.action.GetBooleanAction(                "java.util.Arrays.useLegacyMergeSort")).booleanValue();}/** 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; ilow &&                     ((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++];    }}/** * Swaps x[a] with x[b]. */private static void swap(Object[] x, int a, int b) {Object t = x[a];    x[a] = x[b];    x[b] = t;}// ComparableTimSort

              1.3、JDK1.8

              2、集合的最大、最小值

              max方法提供了兩種實現

              // 沒有比較器的,那么默認非泛型必須實現了Comparable接口,否則編譯的時候會報錯,因為其底層是調用Comparable的compareTo方法來進行比較的;// 泛型必須繼承Objec且實現Comparable接口;public staticT max(Collection coll) {Iterator i = coll.iterator();    T candidate = i.next();    while (i.hasNext()) {T next = i.next();        if (next.compareTo(candidate) > 0)            candidate = next;    }    return candidate;}// 帶比較器,跟不帶比較器的類似;public staticT max(Collection coll, Comparator comp) {if (comp==null)        return (T)max((Collection) coll);    Iterator i = coll.iterator();    T candidate = i.next();    while (i.hasNext()) {T next = i.next();        if (comp.compare(next, candidate) > 0)            candidate = next;    }    return candidate;}

              3、多張類型的集合

              Collections對原始集合進行了封裝,提供了:線程安全的集合、不可變的集合;

              [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-R1ReBn5L-1580104538820)(集合/image/Collections-InnerClass.png)]

              3.1、線程安全的集合

              線程安全的集合都是以Synchronized開頭

              SynchronizedListSynchronizedMapSynchronizedSetSynchronizedSortedMapSynchronizedSortedSet

              上述線程安全的集合都是通過synchronized代碼塊來實現的,雖然都是線程安全的,但是在實際應用中避免使用這些類;

              3.2、不可變集合

              不可變集合都是Unmodifiable開頭,這類方法的操作是會從原集合中得到一個不可變的新集合,新集合只能訪問,不能修改;否則拋出異常;

              UnmodifiableCollection:為只讀集合

              static class UnmodifiableListextends UnmodifiableCollectionimplements List{public E set(int index, E element) {// 拋出異常        throw new UnsupportedOperationException();    }    public void add(int index, E element) {// 拋出異常        throw new UnsupportedOperationException();    }    public E remove(int index) {// 拋出異常        throw new UnsupportedOperationException();    }    public int indexOf(Object o)            {return list.indexOf(o);}    public int lastIndexOf(Object o)        {return list.lastIndexOf(o);}    public boolean addAll(int index, Collection c) {// 拋出異常        throw new UnsupportedOperationException();    }    @Override    public void replaceAll(UnaryOperatoroperator) {// 拋出異常        throw new UnsupportedOperationException();    }    @Override    public void sort(Comparator c) {// 拋出異常        throw new UnsupportedOperationException();    }}

              三、Objects

              1、相等

              主要有兩個方法:deepEquals、equals,其中deepEquals主要是判斷數組的,后面equals主要判斷基本類型和自定義類型的

              public static boolean deepEquals(Object a, Object b) {if (a == b)        return true;    else if (a == null || b == null)        return false;    else        return Arrays.deepEquals0(a, b);}public static boolean equals(Object a, Object b) {return (a == b) || (a != null && a.equals(b));}

              2、判空

              Objects.isNull(Object obj)Objects.nonNull(Object obj)Objects.requireNonNull(T obj)Objects.requireNonNull(T obj, String message)Objects.requireNonNull(T obj, SuppliermessageSupplier)

              責任編輯:

              標簽:

              相關推薦:

              精彩放送:

              新聞聚焦
              Top 中文字幕在线观看亚洲日韩