7.Java collection-arrays Class realization principle and Source code analysis

Source: Internet
Author: User
Tags array length comparable shallow copy sorts

One, Arrays.sort () array sorting

Sorting for all types is available in Java arrays. It is mainly divided into primitive (8 kinds of basic types) and object two major categories.

Basic types: fast sorting with tuning;

Object type: An improved merge sort is used.

1, for the basic type of source analysis as follows (take int[] as an example):

Java uses a quick sort of array of primitive (Int,float and other prototype data) to sort the array of object objects by merging. For this distinction, Sun's explanations in <<the Java tutorial>> are as follows:

The sort operation uses a slightly optimized merge sort algorithm that's fast and stable:

* fast: it is guaranteed to run in n log (n)   time and runs substantially faster on nearly sorted lists.  empirical tests showed it to be as fast as a highly  optimized quicksort. a quicksort is generally considered to be  Faster than a merge sort but isn ' T&NBSP;STABLE&NBSP;AND&NBSP;DOESN ' t  Guarantee n log (n)  performance.

* Stable:it doesn ' t reorder equal elements. This is important if you sort the same list repeatedly on different attributes. If a user of a mail program sorts the Inbox by mailing date and then sorts it by sender, the user naturally expects that T He now-contiguous list of messages from a given sender would (still) be sorted by mailing date. This is guaranteed only if the second sort was stable.

In other words, the optimized merge sort is fast (Nlog (n)) and stable.

For the ordering of objects, stability is important. such as the report card, the beginning may be according to the number of people in the order of the line, and now let us use scores platoon, then you should ensure that the original Zhang San in front of John Doe, even if their results are the same, Zhang San can not run to the back of John Doe.

The fast sort is unstable, and the worst-case time complexity is O (n^2).

In addition, the object array is only a reference to the object, so multiple shifts do not cause additional overhead, but the object array is generally more sensitive to the comparison, it is possible that the comparison of the object is much more expensive than the simple number. Merge sort is better than fast sorting in this respect, which is one of the important reasons to choose it as an object sort.

Sorting optimization: The implementation of the fast and merge are recursive, and at the bottom of the recursion, that is, the array length to be sorted is less than 7 o'clock, the direct use of bubble sort, and no longer recursive.

Analysis: An array of length 6 bubble sort the total number of comparisons is 1+2+3+4+5+6=21 times, preferably only 6 times compared. The overhead of a quick row or merge involves recursive invocation, and its time efficiency is highlighted at the lesser of N, so a bubbling sort is used, which is an extremely important optimization for fast sequencing.

The rapid sequencing in the source code, mainly to do the following several aspects of optimization:

1) When the number of elements in the array to be sorted is small, the threshold value in the source code is 7, and the insertion sort is used. While insertion sorting has a time complexity of 0 (n^2), insertion sorting is preferable to fast sorting when there are fewer array elements, because recursive operations that quickly sort affect performance.

2) Better selection of the partition element (datum element). The ability to divide an array into roughly two equal parts avoids the worst case scenario. For example, when the array is ordered, selecting the first element as the partition element will make the time complexity of the algorithm reach O (n^2).

The method of selecting the partition element in the source code:

When the array size is size=7, the middle element of the array is taken as the dividing element. int n=m>>1; (This method is worth learning)

When the size of the array is 7<size<=40, the elements of the middle size of the first, middle, and last three elements are taken as the dividing element.

When the size of the array is size>40, select 9 elements from the array to be spaced evenly, and choose a pseudo-median as the dividing element.

3) According to the division of the V, the formation of the invariant v* (<v) * (>v) * v*

Ordinary fast sorting algorithm, after a division, will be divided into the middle of the group of elements, the left element is less than the partition element, the right element is greater than the partition element, and not the element equal to the partition is placed near it, this, in the Arrays.sort () has been greatly optimized.

Examples: 15, 93, 15, 41, 6, 15, 22, 7, 15, 20

Because of 7<size<=40, select v = 15 as the dividing element in 15, 6, and 20.

After a break: 15, 15, 7, 6, 41, 20, 22, 93, 15, 15. Elements equal to the dividing element are moved to both sides of the group.

The next step is to move the elements equal to the element into the middle of the array, forming: 7, 6, 15, 15, 15, 15, 41, 20, 22, 93.

Finally, the two intervals are sorted by recursion [7, 6] and [41, 20, 22, 93].

Part of the source code (a) is as follows:

1 package com.util;  2 3 public class Arraysprimitive {4 private arraysprimitive () {} 5 6/** 7 * Sorts the specified array of type int in ascending order of numbers. 8 */9 public static void sort (int[] a) {Sort1 (A, 0, a.length); 11} 12 13/** 14 * Sorts the specified range for the specified array of type int in ascending order of numbers.  * * * public static void sort (int[] A, int fromIndex, int toindex) {Rangecheck (a.length, FromIndex, Toindex); Sort1 (A, FromIndex, Toindex-fromindex); 22 * * private static void Sort1 (int x[], int off, int len) {23 * * * * * * * When the number of elements in the array to be sorted is less than 7 o'clock Sort by insert. 24 * 25 * Although insertion sequencing has a time complexity of O (n^2), insertion sorting is better than fast sorting when there are fewer elements in the array, because recursive operations that quickly sort affect performance.  + * IF (Len < 7) {(int i = off; I < Len + off; i++) (int j = i; j > off && x[j-1] > X[j]; j--) swap (x, J, j-1); return; 32} 33/* 34 * When the number of elements in the array to be sorted is greater than or equal toAt 7 o'clock, a quick sort is used. * Choose a partition element, v 37 * Select a partition element, v 38 * 39 * Better choice of partition element (datum element) 。 The ability to divide an array into roughly two equal parts avoids the worst case scenario. For example, when an array is ordered, 40 * selects the first element as the partition element, which will make the algorithm's time complexity reach O (n^2). 41 */42//When the array size is size=7, the middle element of the array is taken as the dividing element. int m = off + (len >> 1); 44//When the array size is 7<size<=40, the elements of the middle size of the first, middle, and last three elements are taken as the dividing element.             if (Len > 7) {len-1 int l = off; int n = off + +; 48/* 49 * When the size of the array is size>40, select 9 elements from the array to be lined up evenly, 50 * Choose a pseudo-median as the dividing element.  * * * if (len > +) {len/8 int s = n, L = med3 (x, L, L + S, L + 2 * s); m = med3 (x, M-s, M, M + s); A. N = med3 (x, n-2 * s, N-N.); 57} 58//Remove the position of the middle-sized element. m = med3 (x, L, M, N); Mid-size, Med of 3 60} 61 62//get divided into Yuan V and Int v = X[m];  +//Establish invariant:v* (<v) * (>v) * v* int a = off, B = A, c = off + len-1, D = C;                     70 while (true) {<= (b-C && x[b] <= v) {if (x[b] = =) Swap (x, a++, b); b++;                     (c >= b && x[c] >= v) {X[c] = = v) 75 Swap (x, C, d--); c--; (b > C); (x, b++, c--); Bayi}//Swap partition elements back to middle with an 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); Recursively sort non-partition-elements if ((s = b-a) > 1) sort1 (x, off, s); if (s = d-c) > 1) sort1 (x, N-S, S.); 94/** * Swaps X[a] with x[b].         * */98 private static void swap (int x[], int a, int b) {in-the-int t = x[a];100 X[a] = x[b];101 X[B] = t;102}103 104/**105 * Swaps x[a. (a+n-1)] With X[b. (b+n-1)]. 106 */107 private static void Vecswap (int x[], int A, int b, int n) {108 for (int i=0; i<n; i++, a++, b++) 109 Swap (x, a, b);}111/**113 * Returns The index of the median of the three indexed integer s.114 */115 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) 117: (X[b] > X[c]? b:x[a] > X[c]? c:a)); 118} 119/**121 * Check that FromIndex and Toindex is in range, and throw an122 * appropriate exception if the y aren ' t.123 */124 private static void Rangecheck (int arraylen, int frOmindex, int toindex) {fromIndex > Toindex) 126 throw new IllegalArgumentException ("Frominde             X ("+ fromIndex127 +") > Toindex ("+ Toindex +") ") if (FromIndex < 0) 129 throw new ArrayIndexOutOfBoundsException (FromIndex); if (Toindex > Arraylen) 131 throw new ARR Ayindexoutofboundsexception (Toindex); 132}133}

The test code is as follows:

1 package com.test; 2  3 import com.util.ArraysPrimitive; 4  5 public class Arraystest {6 public     static void Main (string[] args) { 7         int [] a={15,93,15,41,6,15,22,7,15,20}; 8        arraysprimitive.sort (a); 9 for         (int i=0;i<a.length;i++) { Ten             System.out.print (a[i]+ ",");        }12         //Result: 6,7,15,15,15,15,20,22,41,93,13    }14}

2, for the object type source code analysis is as follows:

Part of the source code (ii) is as follows:

1 package com.util;  2 3 Import Java.lang.reflect.Array;  4 5 public class Arraysobject {6 private static final int insertionsort_threshold = 7; 7 8 Private Arraysobject () {} 9 public static void sort (object[] a) {//java.lang.object.clone () , understand deep table copy and shallow copy object[] aux = (object[]) a.clone (); MergeSort (aux, A, 0, a.length, 0); + public static void sort (object[] A, int fromIndex, int toindex) {Rangecheck (a.length, Fromin Dex, Toindex); object[] aux = Copyofrange (A, FromIndex, Toindex); MergeSort (aux, A, FromIndex, Toindex,-fromindex); /** * SRC is the source array, starts at index 0 * Dest is the (possibly larger) arr Ay destination with a possible offset (* low)-the index in dest to start sorting-high-is the end index   In dest to end sorting * off are the offset to generate corresponding low, high in SRC 28 */29  private static void MergeSort (object[] src, object[] dest, int low, int. int high, int off) {to int l Ength = high-low; +//insertion sort on smallest arrays if (length < Insertionsort_threshold) {F or (int i = low, i < high; i++)-(int j = i; j > Low && 37 ( Comparable) (Dest[j-1]). CompareTo (Dest[j]) > 0; j--) (dest, J, J-1); The return; +//Recursively sort halves of dest into src + int destlow = low; Desthigh int = high; Low + = off; + + + off; */* &GT;&GT;&GT;: Unsigned Right shift operator * Expression1 >>> expresion2:expression1 each bit to the right to move expr Ession2 50 * The number of digits specified. The number of left-vacated digits after the right shift is filled with zeros. Move out the right bit is discarded. 51 * For example:-14>>>2; results are: 1073741820 */Int. INT MID = (low + high) >>> 1; The mergeSort (dest, SRC, Low, Mid,-off); MergeSort (dest, SRC, Mid, High,-off); Already/If list is sorted, just copy from Src to dest. This was an optimization///-results in faster sorts for nearly ordered lists. (((comparable) src[mid-1]). CompareTo (Src[mid]) <= 0) {system.arraycopy (src, Low, dest, D Estlow, length); The return; +//Merge sorted halves (now in SRC) to dest (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++];     /** * Check that FromIndex and Toindex is in range, and throw a appropriate 76 * exception if they aren ' t. * * +/-private static void Rangecheck (int arraylen,int fromIndex, int toindex) {if (FromIndex > Toindex) throw new IllegalArgumentException ("fr Omindex ("+ fromIndex Bayi +") > Toindex ("+ Toindex +") "); if (FromIndex < 0) The new arrayindexoutofboundsexception (FromIndex); if (Toindex > Arraylen)-throw new ArrayIndexOutOfBoundsException (Toindex); (t[) Copyofrange (t[] original, int from, int to) {Copyofrange (Original, From, to, (class<t[]>) Original.getclass ()); <t, u> t[] Copyofrange (u[] original, int from, int. to, CLASS&LT;? ex Tends t[]> newType) {94 int newlength = To-from; if (Newlength < 0)-throw new I Llegalargumentexception (from + ' > ' + to); t[] Copy = ((object) NewType = = (object) object[].class) 98? (t[]) New Object[newlength] (t[]) array.newinstance (Newtype.getcomponenttype (), newlength), System.arraycopy (original     , from, copy, 0,101 math.min (Original.length-from, Newlength)); 102 Return copy;103}104 105 /**106 * Swaps X[a] with x[b].107 */108 private static void Swap (object[] x, int a, int b) {109 Ob Ject t = x[a];110 x[a] = x[b];111 X[b] = t;112}113}

The test code is as follows:

1 package com.test; 2 3 Import Com.util.ArraysObject; 4 5 public class Arraysobjectsorttest {6 public static void main (string[] args) {7 Student stu1=new Student (1001,100.0f); 8 Student stu2=new Student (1002,90.0f); 9 Student stu3=new Student (1003,90.0f); Student stu4=new Student (1004,95.0f); student[] stus={ Stu1,stu2,stu3,stu4};12//arrays.sort (Stus); Arraysobject.sort (Stus), + for (int i=0;i<stus.len gth;i++) {System.out.println (Stus[i].getid () + ":" +stus[i].getscore ()); 16}17/* 1002:90.01 8 * 1003:90.019 * 1004:95.020 * 1001:100.021 */22}23}24 class Student Implemen  TS comparable<student>{25 private int id;  Study number: private float score; Grade Student () {}28 public Student (int id,float score) {this.id=id;30 this.score=score;3 1}32 @Override33 public int compareTo (Student s) {34        return (int) (This.score-s.getscore ()),}36 public int getId () {PNS return id;38}39 public void setId (int id) {this.id = id;41}42 public float Getscore () {p return score;44}45 ublic void SetScore (float score) {This.score = score;47}48}

Auxiliary Understanding Code:

1 package Com.lang;  2 3 Public final class System {4//system class cannot be instantiated.  5 Private System () {} 6//In the facilities provided by the system class, there are standard input, standard output and error output streams, access to externally defined properties 7//And environment variables, methods for loading files and libraries, and a practical way to quickly copy part of an array. 8/** 9 * src and dest must be of the same type or an array of types that can be converted.     Ten * @param src the source array.11 * @param srcpos starting position in the source array.12     * @param dest The destination array.13 * @param destpos starting position in the destination data.14 * @param length The number of array elements to is copied.15 */16 public static native void Arraycopy (Ob ject src, int srcpos, Object dest,17 int destpos, int length);}1 package com.lang.reflect; 2 3 Public final class array {4 private array () {} 5 6//Create a new array with the specified component type and dimension. 7 public static Object newinstance (class<?> componenttype, int length) 8 throws Negativearraysizeexc Eption {9 return NewArray (componenttype, length); 10    }11 private static native Object NewArray (Class componenttype, int length) throws Negativearraysi ZEEXCEPTION;14}

Second, arrays.aslist

Use the Contains method of ArrayList, using HashSet's contains method instead

In the launch of an application, found that there is a data load in a few minutes, just beginning to think that it is necessary to load the data more reason, check the database has 6 or so, but a separate write a method of data read, will be read over the 60,000, but only need less than 10 seconds, I think there must be a problem in this, so look carefully at the logic, which has a piece of data to the logic of the heavy, is that there are several fields in the record is the same, it is considered to be duplicate data, you need to filter out the duplicate data. Here, a list is used to hold the primary key of these fields, and if the same is not done, the code is just the following:

1 list<string> uniquekeylist = new arraylist<string> ();  2//...  3 if (Uniquekeylist.contains (UniqueKey)) {  4                    continue;    }

Depending on the key to find out if it already exists, to determine whether to duplicate the data. After analysis, this piece consumes a lot of time, so go to look at the source of ArrayList's contains method, discover that it will eventually call his own IndexOf method:

7public int indexOf (Object elem) {  8    if (Elem = = null) {  9 for        (int i = 0; i < size; i++  )        if (elementdata[i]==null)  One            return i;  The    else {(        int i = 0; i < size; i++)        if (elem.equals (Elementdata[i]))  15
   
    return i;  +    return-1;  (+    }  
   

So what he did here is to traverse the entire list to find the most likely to find a key to reach more than 60,000 times, that is, the entire list will be scanned, the blame will be so slow.

The original list is then replaced with the set:

set<string> uniquekeyset = new hashset<string> ();  //......  if (Uniquekeyset.contains (UniqueKey)) {                      continue;  

Speed on the go up, in the weight of this piece up to spend a second, why HashSet speed went up, that is because its internal use is Hashtable, this is HashSet contains source:

Public Boolean contains (Object o) {     return Map.containskey (o);  

About Unsupportedoperationexception Exceptions

A java.lang.UnsupportedOperationException exception occurred when calling Add,remove these method after using Arrays.aslist (). This is because Arrays.aslist () returns java.util.arrays$arraylist instead of ArrayList. Arrays$arraylist and ArrayList are inherited Abstractlist,remove,add etc. method in Abstractlist is the default throw Unsupportedoperationexception and does not do anything. ArrayList override these method to manipulate the list, but Arrays$arraylist does not override remove (), add (), etc., so the throw Unsupportedoperationexception.

7.Java collection-arrays Class realization principle and Source code analysis

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.