Series Article Directory
Self-implementation of dynamic array (ArrayList) of linear table - Programmer Sought
Article directory
- foreword
- 1. Analysis of the three construction methods of ArrayList
- 2. How does ArrayList expand? (Source code analysis)
- 3. Common methods of ArrayList
- Four, three kinds of traversal of ArrayList
- 5. Defects of ArrayList
foreword
1. Analysis of the three construction methods of ArrayList
method | explain |
ArrayList
()
|
No-argument constructor
|
ArrayList
(Collection<? extends E> c)
|
Build ArrayList from other
Collections
|
ArrayList
(int initialCapacity)
|
Specify the initial capacity of the sequence table
|
public static void main(String[] args) {
ArrayList<Integer> arrayList1 = new ArrayList<>();
ArrayList<Integer> arrayList2 = new ArrayList<>(12);
arrayList1.add(1);
ArrayList<Integer> arrayList3 = new ArrayList<>(arrayList1);
System.out.println(arrayList3);
}
Note: When using the constructor of ArrayList (Collection<? extends E> c), because this is the upper bound of wildcards, note that the type passed in must be E or a subclass of E.
2. How does ArrayList expand? (Source code analysis)
First look at the constructor without parameters:
DEFAULT_CAPACITY = 10 The default capacity is 10; transient Object[] elementData, similar to the array behind the sequence table; private int size , size is the number of valid elements, which is 0 at this time, indicating that the length of DEFAULTCAPACITY_EMPTY_ELEMENTDATA is 0, this construction method does not Allocate array memory.
So now there is a question, why is the length of DEFAULTCAPACITY_EMPTY_ELEMENTDATA being 0 and the default capacity being 10 contradictory? There is no size at this time, so how did you put it in when adding data for the first time?
Next, we continue to click to enter the add method:
When describing the storage element, it is placed after the last element by default. But a ensureCapacityInternal(size + 1) method is used here, we are clicking to enter,
At this time, size is 0. When size+1 is passed in, minCapacity is 1; then there are two more methods. The return value of the calculateCapacity(elementData, minCapacity) method should be used as the parameter of the ensureExplicitCapacity() method. .
Then we click to enter the calculateCapacity(elementData, minCapacity) method. Here, as the name implies, it is to calculate the capacity. At this time, minCapacity is 1, because the construction method without parameters is called at this time, then elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA at this time.
At this time, if the If statement is satisfied, then the maximum value will be calculated. At this time, minCapacity is 1, DEFAULT_CAPACITY = 10, so when add is called for the first time, 10 will be returned at this time. Then at this time, the return value of 10 will be used as the parameter of ensureExplicitCapacity(), then we click to enter the inside of this method:
At this time, the minCapacity is 10, and the length of the elementData array is 0. If 10-0 > 0, then the grow function will be called to pass 10. Let's click grow again to enter this function:
At this time, oldCapacity and newCapacity are calculated to be 0, because 0 - 10 < 0, then newCapacity = minCapacity = 10. Next, look at the following if statement:
At this time, MAX_ARRAY_SIZE is the maximum value of int minus 8. At this time, the if statement cannot come in and continues to execute, then the array is actually allocated memory at this time.
elementData = Arrays.copyOf(elementData, newCapacity);
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
Equivalent to ensureCapacityInternal(size + 1) this method is finished, the capacity of the array is 10, and then the elements can be put in. So it can be concluded that the premise is that the constructor without parameters is called. When adding for the first time, the default capacity is 10.
So how does it scale? Like when putting the 11th element?
Next, we continue to look at the grow function.
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//按照1.5倍方式扩容
int newCapacity = oldCapacity + (oldCapacity >> 1);
// 如果用户需要扩容大小 超过 原空间1.5倍,按照用户所需大小扩容
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
// 如果需要扩容大小超过MAX_ARRAY_SIZE,重新计算容量大小
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}
int newCapacity = oldCapacity + (oldCapacity >> 1); In fact, this code is expanding, and it is 1.5 times the expansion.
In fact, the construction method with parameters, how much the initial value is given, then what is the initial capacity:
The construction method of ArrayList (Collection<? extends E> c) is actually an array copy:
summary:
3. Common methods of ArrayList
method | explain |
boolean
add
(E e)
|
tail plug
e
|
void
add
(int index, E element)
|
Insert
e
at
index
position
|
boolean
addAll
(Collection<? extends E> c)
|
tail insert
element in
c
|
E
remove
(int index)
|
remove the
element at
index position
|
boolean
remove
(Object o)
|
delete the first
o encountered
|
E
get
(int index)
|
Get the subscript
index
position element
|
E
set
(int index, E element)
|
Set the subscript
index
position element to
element
|
void
clear
()
|
empty
|
boolean
contains
(Object o)
|
Determine if
o
is in a linear table
|
int
indexOf
(Object o)
|
Returns the subscript where the first
o is located
|
int
lastIndexOf
(Object o)
|
Returns the subscript of the last
o
|
List<E>
subList
(int fromIndex, int toIndex)
|
Intercept part of the
list
|
Here we need to pay attention to the method List<E> subList (int fromIndex, int toIndex):
public static void main(String[] args) {
ArrayList<Integer> arrayList1 = new ArrayList<>();
arrayList1.add(1);
arrayList1.add(2);
arrayList1.add(3);
arrayList1.add(4);
arrayList1.add(5);
List<Integer> list = arrayList1.subList(1,3);
System.out.println(list);//2,3
list.set(0,99);
System.out.println(arrayList1);// 1,99,3,4,5
System.out.println(list);//99,3
}
This will find that if the data in the list is modified, the data in the arraylist will also be modified. Take a look at a memory map to see what's going on.
Four, three kinds of traversal of ArrayList
ArrayList can be traversed in three ways: for loop + subscript , foreach , using iterator
public static void main(String[] args) {
ArrayList<Integer> arrayList1 = new ArrayList<>();
arrayList1.add(1);
arrayList1.add(2);
arrayList1.add(3);
arrayList1.add(4);
arrayList1.add(5);
int size = arrayList1.size();
for (int i = 0; i < size; i++) {
System.out.print(arrayList1.get(i)+" ");
}
System.out.println();
for (int x : arrayList1) {
System.out.print(x+" ");
}
System.out.println();
Iterator<Integer> it = arrayList1.iterator();
while (it.hasNext()) {
System.out.print(it.next()+" ");
}
}