Array (2): Implementation of ArrayList and Use of Arrays Class

Keywords: Java

Can arrays be lengthened?

We all know that the length of the array must be given when initializing. Because of this length problem, we are more inclined to use containers in actual development, such as ArrayList, etc. When using container classes, we do not need to consider the length problem, because the container has already handled for us, then the array can not be lengthened? Of course not. ArrayList is based on arrays. Let's see how ArrayList is handled.

2. Principle of ArrayList Implementation

ArrayList uses an Object array as its internal operation, and a member variable size represents the length of the container.

    private transient Object[] elementData;
    private int size;

When adding data, call the add() method:

public boolean add(E e) {
      ensureCapacityInternal(size + 1);  // Increments modCount!!
      elementData[size++] = e;
      return true;
 }

When you call add, you first call the ensureCapacityInternal method, which aims to expand the size of the array by 1

private void ensureCapacityInternal(int minCapacity) {
     modCount++;
     // overflow-conscious code
     if (minCapacity - elementData.length > 0)
         grow(minCapacity);
}

In ensure Capacity International, we first determine whether there is an overflow problem in expansion, and if there is no overflow problem, we call grow to expand.

    private void grow(int minCapacity) {
        // Overflow processing
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        if (newCapacity - MAX_ARRAY_SIZE > 0)
            newCapacity = hugeCapacity(minCapacity);
        // Capacity expansion
        elementData = Arrays.copyOf(elementData, newCapacity);
    }

This is the core of the expansion code, the previous code is overflow processing, the key is the last sentence.

elementData = Arrays.copyOf(elementData, newCapacity)

The API document is interpreted as copying the specified array, intercepting or filling it with null or 0 (if necessary) to give the copy the specified length.

That is, by Arrays.copyOf, the length of the array elementData is extended to newCapacity, and the expanded partial filling is determined by the array type.

For example:

        int[] a = new int[]{1,2};
        System.out.println("Length before expansion:" + a.length);
        a = Arrays.copyOf(a, 3);
        System.out.println("Length after expansion:" + a.length);
        System.out.println("Filled data:" + a[2]);

Output:
Length before expansion: 2
Length after expansion: 3
Filled data: 0

III. Use of Array Class

The Arrays class contains various methods for manipulating arrays (such as sorting and searching), which must be used skillfully!
Common methods of this kind are:

Method explain
asList(T… a) Returns a fixed-size list supported by a specified array
copyOf(int[] original,int newLength) Duplicate the specified array, and the filled data is determined by the array type so that the copy has the specified length
copyOfRange(long[] original, int from, int to) Copies the specified range of the specified array to a new array
equals(int[] a, int[] a2) Returns true if two specified int arrays are equal to each other
fill(int[] a, int val) Assign the specified int value to each element of the specified int array
sort(int[] a) Sort the specified int array in ascending order
The above example is only an array of int type, the same operation as other types of arrays.

4. Shallow Copy of Arrays, CopOf Problem

When the array type is not the basic data type, the reference of the object is stored in the array, so when copyOf replicates the array of objects, it is important to note that the reference of the replicated object is not the object itself!

class Person{
    int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

public class Array2 {

    public static void main(String[] args) {
        Person p = new Person();
        p.setAge(20);
        Person[] a = new Person[]{p};
        Person[] b = Arrays.copyOf(a, a.length);
        a[0].setAge(30);
        System.out.println("a Age:" + a[0].getAge());
        System.out.println("b Age:" + b[0].getAge());
    }
}

Output:
Age of a: 30
b Age: 30

You can see that when a changes its value, even the value of b changes. That's the shallow copy problem.

For blog posts on deep and shallow copies, please refer to:
Gradually analyze the shallow and deep copies of java: http://www.cnblogs.com/chenssy/p/3308489.html.

Posted by ashwin on Sat, 23 Mar 2019 17:51:52 -0700