Getting a set of Java source code analysis ArrayList Series (seven)

Foreword

On a line by us to achieve a similar class ArrayList basic functions, and of course a lot of lack of consideration, we learn just to be prepared with the collection, ArrayList this section we look at the source code for the common method of operation is how to proceed, please look down.

ArrayList source code analysis

On a content (Portal " https://www.cnblogs.com/CreateMyself/p/11440876.html ") we instantiate the console as a ArrayList, and add a data follows

  ArrayList<Integer> list = new ArrayList<>();
  list.add(1);

Initial capacity analysis

Examples of the first set of ArrayList, we write on a basic operation of a class queue, we finally, the capacity of the array in the constructor is performed by optimizing, if not given the capacity of the array given a default capacity, then Let's look at the source code to initialize a collection in the end what had been done the preparatory work ahead of it?

public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
 }


public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
.....

When we initialize the collection of basic data types and the type, as there two functions, one is the default constructor is a constructor parameters. Because the example given parameter is not included, so it is to take following a constructor, we look at the ArrayList variable defined as follows:

    // default initial capacity 
    Private  static  Final  int DEFAULT_CAPACITY = 10 ; 

    // empty array Examples 
    Private  static  Final Object [] EMPTY_ELEMENTDATA = {}; 

    // default empty array Examples 
    Private  static  Final Object [] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; 

    // operated array 
    transient Object [] elementData of; 

    // array size 
    Private  int size; 

    // array maximum capacity 
    Private  static  Final  int MAX_ARRAY_SIZE Integer.MAX_VALUE = -. 8;

As we have not a given capacity, initializing an empty array example, if we have a given capacity, the first take as a constructor, we compared the capacity of a given capacity is greater than 0 if the capacity of the array, is equal to 0 if an empty array instance, or throw an illegal capacity. Next to the second step, when we add the element 2, add methods to see how the operation.

Add elemental analysis

// add elements to achieve 
public  Boolean the Add (E E) { 
        ensureCapacityInternal (size +. 1 ); 
        elementData of [size ++] = E;
         return  to true ; 
}

We continue to look ensureCapacityInternal (size + 1) method, which is used to calculate the capacity of the array, the method to achieve the final look as follows:

private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
    // computing capacity 
    Private  static  int calculateCapacity (Object [] elementData of, int be minCapacity) {
         // when not given array capacity or capacity is designated 0 instantiating set, then this time the array is empty array example 
        IF (== elementData of DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
             // At this time minCapacity 1, and by Math.max function minCapacity DEFAULT_CAPACITY (default size) [10] Compare Back 
            return Math.max (DEFAULT_CAPACITY, minCapacity); 
        } 
        // array capacity when given instantiation is greater than 0, the process directly returns to add capacity after an element i.e. (+ size. 1) 
        return be minCapacity; 
    }
    // determines whether expansion 
    Private  void ensureExplicitCapacity ( int be minCapacity) { 
        ModCount ++ ; 

        // array capacity after the calculation if the expansion is greater than the length of the array memory 
        IF (be minCapacity - elementData.length> 0 ) 
            Grow (be minCapacity); 
    }
// expansion core implementation 
Private  void Grow ( int be minCapacity) { 

        // is operated array of actual capacity 
        int oldCapacity = elementData.length; 
        
        // new capacity = (actual capacity + actual capacity / 2 and to mode) i.e. 1.5 times the capacity of the old 
        int newCapacity oldCapacity + = (oldCapacity >>. 1); 
        
        // if the new capacity is less than the array size to the new size of the array capacity places 
        IF (newCapacity - be minCapacity <0 ) 
            newCapacity = be minCapacity; 
        
        // if new capacity greater than the maximum array size defined 
        IF ( newCapacity - MAX_ARRAY_SIZE> 0 ) 
            newCapacity = hugeCapacity (be minCapacity); 
            
        // new array after expansion 
        elementData =Arrays.copyOf (elementData of, newCapacity); 
} 


// calculate the maximum capacity of the array 
Private  static  int hugeCapacity ( int be minCapacity) {
         IF (be minCapacity <0) // overflow 
            the throw  new new an OutOfMemoryError (); 
        
        // Maximum array when the array size greater than the defined the maximum size of the new capacity is the maximum integer otherwise defined maximum size of the array         
        return (minCapacity> MAX_ARRAY_SIZE)? 
            Integer.MAX_VALUE: 
            MAX_ARRAY_SIZE; 
}

Above the red mark of the maximum capacity of the array is automatic expansion of the definition, there need to explain oldCapacity >> 1 What do you mean, I have returned to school to learn a teacher, check the information before they get to know, to be a memo here. >> represents the right computer, in most cases we use this operator is relatively small, but here why not direct multiplication and division it? And we also see to understand more, use the left and right shift operation is fast, direct multiplication and division needs to consume cpu computing memory . Just beginning to see that I was ignorant of the force, it is actually very simple. 32 For example, we have a binary representation, compared with 100,000, how to calculate it, as follows:

(1 * 2 ^ 5)+(0 * 2 ^ 4)+(0 * 2 ^ 3)+(0 * 2 ^ 2)+(0 * 2 ^ 1)+(0 * 2 ^ 0)= 32 + 0 + 0 + 0 + 0 + 0 = 32。

 

Well, we know that 32 is represented as a binary [100,000], then 32 >> one said it would be converted to decimal 32 to move a whole, will be left up 0 spare right right after extra Excluding binary, if it is left shift the contrary (to be noted here int is 32, but the number is not so big, so certainly all 0 left side, where we omitted oh), as follows:

The mobile after a 32 rightward in FIG. 1 >>, then the calculation result and the first map, as follows:

(0 * 2 ^ 5)+(1 * 2 ^ 4)+(0 * 2 ^ 3)+(0 * 2 ^ 2)+(0 * 2 ^ 1)+(0 * 2 ^ 0)= 0 + 16 + 0 + 0 + 0 + 0 = 16。

To verify the above results, we look through the code to print correctly, as follows:

 System.out.println( 32 >> 1);

With the above it is easy to conclude FIG: If the right shift >> i.e., the original data by a power of 2 bits and discarding the mold if it is left << i.e., the original data is multiplied by 2 bit power several times . For example, 11 >> 2 by 11 by 2 ^ 2, 2 flew the outcome. If 11 << 2, is 11 * 2 ^ 2, the result will be 44. Source Up to this analysis, we can draw the following conclusions:

If not given initial capacity, the default initial capacity of 10.

Automatic expansion size to 1.5 times the original capacity.

The maximum capacity of Integer.MAX_VALUE that is 2147483647.

Adds the specified index element analysis

We just finished the above analysis and initialize instances of this collection add an element, then we take a look at adding elements specified index, as follows:

public static void main(String[] args) {

        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);

        //添加元素2到索引5
        list.add(5,2);
}

Based on the above analysis we have, because we did not specify when initializing the collection capacity, so when we add an element, a set of capacity at this time of default is 10, then we are at an index of 5 additional element 2, then is not it can it?

We believe that the default capacity of 10, at a specified index element 5 is inserted there is no problem, but the result is an exception is thrown, indicating that the initial capacity is not provided with an array of default capacity or as a basis to judge, but to the actual array size determination is performed, in order to prove our point, we analyze the elements in the method of inserting the specified index, as follows:

// Adds the specified index element 
public  void the Add ( int index, E Element) { 

        // Check the index range, to confirm whether to add 
        rangeCheckForAdd (index); 

        ensureCapacityInternal (size +. 1 ); 
        System.arraycopy (elementData of, index, elementData of, index + . 1 , 
                         size - index); 
        elementData of [index] = Element; 
        size ++ ; 
}
Private  void rangeCheckForAdd ( int index) { 

        // index of the element added can not be larger than the actual size of the array or less than 0, otherwise an exception is thrown 
        IF (index> size || index <0 )
             the throw  new new an IndexOutOfBoundsException (outOfBoundsMsg (index)); 
}

Some people might ask, what's the point analysis of the source code or role in it? Too many roles, one does not appear to understand the nature of the principles behind from that so-called "pit" Twenty and by learning to write high-quality code, the three others. We have to understand the principles, then we will do a title, as follows:

public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);
        list.add(7);
        list.add(8);
        list.add(9);
        list.add(10);
        list.add(6,2);
}

Because we know that the default initial capacity of 10, the 2, then the automatic expansion size and capacity of the element 15 when added to the element 11 i.e. the insertion position index of 6 (or do not know if, over again recommended under review Benpian article). Next we trimToSize analysis method.

trimToSize analysis

First we look at the following piece of code:

public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>(20);
        list.add(1);
        list.add(2);

        list.add(6,2);
        list.trimToSize();
}

As we provide initial capacity of 20, but then our actual results only added only three elements, the remaining 17 elements in the array has occupied the pit, so this time in order to solve this problem on the introduction of trimToSize method to address following three questions

The set is reduced to the current set of actual storage size

Minimizing the set of memory instances

When we need to reduce collection and minimize storage

public  void trimToSize () { 
        ModCount ++ ;
         // if the array size is less than the actual capacity of the array 
        IF (size < elementData.length) {
             // if the current array actual array size is 0 Example array is empty, or to copy the array size 
            elementData of = (size == 0 )
               ? EMPTY_ELEMENTDATA 
              : Arrays.copyOf (elementData of, size); 
        } 
}

remove analysis

In java can delete the index for the specified element location, you can also delete elements directly, let's first take a look at the index remove elements, as follows:

// delete the specified index of the element and returns the value to remove elements 
public E Remove ( int index) {
         // determines whether or not the index is smaller than the actual size of the array, or thrown 
        rangeCheck (index); 

        ModCount ++ ; 
        
        // Get index element 
        E oldValue = elementData of (index); 

        // acquiring copy number of elements in the array to be copied 
        int numMoved size = - index -. 1 ;
         IF (numMoved> 0 ) 
            System.arraycopy (elementData of, index + 1'd , elementData of, index, 
                             numMoved); 
                             
        // It will be deleted as null elements to facilitate recycling garbage collector                      
        elementData of [- size] = null; 

        return oldValue;
}

If we want to direct the elements, such as removing elements added 2 above, this time in particular against overloading delete method parameter is the object, so we need to be converted to a packaging element 2, such as the following:

// delete the specified element 
public  Boolean Remove (Object O) {
         // if the object is empty 
        IF (O == null ) {
             // iterate 
            for ( int index = 0; index <size; index ++ )
                 // find the array empty elements 
                IF (elementData [index] == null ) {
                     // find out the index of the element where quick removal 
                    fastRemove (index);
                     // returns deleted successfully 
                    return  to true ; 
                } 
        } the else {
             // if the object is not empty
            for ( int index = 0; index <size; index ++ )
                 // find the element in the array satisfies the condition of the 
                IF (o.equals (elementData of [index])) {
                     // find the index element is located to quickly remove 
                    fastRemove (index);
                     // returns deleted successfully 
                    return  to true ; 
                } 
        } 
        // return deletion failed 
        return  false ; 
} 
    
    
// quickly remove (by way of replication in nature)     
Private  void fastRemove ( int index) { 
  
    modCount ++ ;
     int numMoved = size - index - 1;
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                         numMoved);
    elementData[--size] = null;
}

In fact, we see a lot of source code inside the methods of operation are based on the method to copy, delete and add collection and so on, while we note that in the above example there will be set to empty, copy the following when it comes to us a little where do under study significance?

public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(6);

        Integer[] array = list.toArray(new Integer[0]);

        System.arraycopy(array, 3, array, 2,
                3);

        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
}

As we provide replication method by calling system simulation deleted, we remove the element array 3, and then print the elements in the array, as follows:

The term call replication, replication of the starting position of the index 3, 4, 5 and the elements in the array may be reproduced, but the original array elements 3,4,5 were covered, but this time the element 6 no cover elements, so there are still six array elements, so in order to GC, we need an element 6 is set to null, and the length is set to 5, this is the best code will reach the same elementData when deleting elements [ --size] = null same effect.

to sum up 

In this section we analyze in detail the source ArrayList more commonly used several methods, of course, such as java 8 no further details appear to be traversed by an explanation of lambda expressions, used the subsequent discovery when studying or doing projects What's missing, I will come back to the study, for the time being here so far, the next section we continue to learn from other collection and analysis of source code, thank you for reading, see the next section.

Guess you like

Origin www.cnblogs.com/CreateMyself/p/11442734.html