JDK1.8集合框架原始碼分析一-------------ArrayList
阿新 • • 發佈:2018-12-12
1.ArrayList初始化
1.1 無參建構函式,預設一個空陣列
1.2 帶容量的有參建構函式:根據容量引數的值範圍來初始化
1.3 原始碼中陣列預設的初始容量為 :10
1.4 原始碼中陣列預設的最大容量為:Integer.MAX_VALUE - 8
2.ArrayList 新增元素
2.1 陣列擴容
2.2 新增元素
從下面的程式碼可以得出如果陣列的初始容量為1,那麼陣列擴容後的陣列容量為 2;
因為 陣列容量為1時,第一次新增元素時,不用擴容
當第二次新增時,才需要擴容,
這時 size = 1 ---> minCapacity = size + 1 = 2
oldeCapacity = 1
newCapacity = 1 + 1 >> 1 = 1 + 0 = 1
所以: newCapacity - minCapacity = -1 < 0 ----> newCapacity = minCapacity = 2
//新增元素 public boolean add(Object e) { //陣列擴容 ensureCapacityInternal(size + 1); elementData[size++] = e; return true; } //陣列擴容 private void ensureCapacityInternal(int minCapacity) { //如果資料為空陣列 // -即初始化的時候,使用的是無參建構函式 // 或者使用的是0容量的有參建構函式 // 從預設的陣列容量和傳遞的陣列最小容量中取較大的值 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } //如果當前陣列的容量大於需要新增元素所需的最小容量,則不需要擴容 if(minCapacity < elementData.length){ return; } //當前陣列的容量 int oldCapacity = elementData.length; //擴容後的陣列容量=當前陣列的容量*1.5 int newCapacity = oldCapacity + oldCapacity >> 1; //如果擴容後的容量比陣列最小容量小, // 則直接使用陣列的最小容量作為擴容後的陣列的容量 if(newCapacity - minCapacity < 0){ newCapacity = minCapacity; } //根據新的容量建立新的陣列 //把當前陣列的資料拷貝到新的陣列中去 elementData = Arrays.copyOf(elementData,newCapacity); }
3.ArrayList指定位置新增元素
3.1 陣列越界檢查,即指定位置是否越界
3.2 陣列擴容
3.3 新增元素
public boolean add(int index, Object e) {
rangeCheckForAdd(index);
//陣列擴容
ensureCapacityInternal(size + 1);
// 0 1 2 3 4 --- size = 5
// A B D E F --- 在D位置上插入C元素 index = 2
// 需要把D E F 元素整體向後移動一位 變成 A B D D E F
// 然後在把index=2 的位置替換成新的元素C即可
// 則是直接在陣列的最後新增要給元素,無需移動陣列,直接新增元素
if (index != size)
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = e;
size++;
return true;
}
private void rangeCheckForAdd(int index) {
if (index > size || index < 0) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + size;
}
4.ArrayList 根據下表移除元素
4.1 陣列越界檢查
4.2 陣列移動
4.3 陣列最後一個元素置空
@Override
public E remove(int index) {
rangeCheck(index);
E oldValue = (E) elementData[index];
fastRemove(index);
return oldValue;
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
private void fastRemove(int index) {
//A B C D E 如果index = 2 即移除 C元素
//只需把 D E 整體向前移動一位,A B D E E
// 然後把最後一位置空即可 A B D E null
// step1 算出移動元素的個數
int numMov = size - index - 1;
// step2 如果移動的元素個數大於0,則移動陣列
// 如果移動的元素等於0,則說明刪除的元素是最後一個元素,直接置空即可
if (numMov > 0)
System.arraycopy(elementData, index + 1, elementData, index, numMov);
elementData[--size] = null;
}
5.ArrayList 指定元素刪除
5.1 找出陣列中第一個滿足指定元素的下標 也就是說jdkArrayList元素只能刪除首個滿足條件的資料,不能刪除所有滿足
條件的元素
5.2 利用下標刪除元素
@Override
public boolean remove(Object obj){
if(obj == null){
for (int index = 0; index < size; index++) {
if (elementData[index] == null) {
fastRemove(index);
return true;
}
}
}else {
for (int index = 0; index < size; index++) {
if(obj.equals(elementData[index])){
fastRemove(index);
return true;
}
}
}
return false;
}
6.自己手寫的ArrayList原始碼程式碼以及Junit測試類
package com.roger.collection;
public interface RogerList<E> {
boolean add(E e);
boolean add(int index, E e);
E get(int index);
int size();
E remove(int index);
boolean remove(Object obj);
}
package com.roger.collection.impl;
import com.roger.collection.RogerList;
import java.util.Arrays;
public class RogerArrayList<E> implements RogerList<E> {
private final int DEFAULT_CAPACITY = 10;
private final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
private Object[] elementData;
private int size;
public RogerArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
public RogerArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity:" + initialCapacity);
}
}
@Override
public boolean add(E e) {
//陣列擴容
ensureCapacityInternal(size + 1);
elementData[size++] = e;
return true;
}
@Override
public boolean add(int index, E e) {
rangeCheckForAdd(index);
//陣列擴容
ensureCapacityInternal(size + 1);
// 0 1 2 3 4 --- size = 5
// A B D E F --- 在D位置上插入C元素 index = 2
// 需要把D E F 元素整體向後移動一位 變成 A B D D E F
// 然後在把index=2 的位置替換成新的元素C即可
//如果index == size
// 則是直接在陣列的最後新增要給元素,無需移動陣列,直接新增元素
if (index != size)
System.arraycopy(elementData, index, elementData, index + 1, size - index);
elementData[index] = e;
size++;
return true;
}
private void rangeCheckForAdd(int index) {
if (index > size || index < 0) {
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
}
private String outOfBoundsMsg(int index) {
return "Index: " + index + ", Size: " + size;
}
private void ensureCapacityInternal(int minCapacity) {
//如果資料為空陣列
// -即初始化的時候,使用的是無參建構函式
// 或者使用的是0容量的有參建構函式
// 從預設的陣列容量和傳遞的陣列最小容量中取較大的值
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
//如果當前陣列的容量大於需要新增元素所需的最小容量,則不需要擴容
if (minCapacity < elementData.length) {
return;
}
//當前陣列的容量
int oldCapacity = elementData.length;
//擴容後的陣列容量=當前陣列的容量*1.5
int newCapacity = oldCapacity + oldCapacity >> 1;
//如果擴容後的容量比陣列最小容量小,
// 則直接使用陣列的最小容量作為擴容後的陣列的容量
if (newCapacity - minCapacity < 0) {
newCapacity = minCapacity;
}
//根據新的容量建立新的陣列
//把當前陣列的資料拷貝到新的陣列中去
elementData = Arrays.copyOf(elementData, newCapacity);
}
@Override
public E get(int index) {
rangeCheck(index);
return (E) elementData[index];
}
@Override
public E remove(int index) {
rangeCheck(index);
E oldValue = (E) elementData[index];
fastRemove(index);
return oldValue;
}
private void rangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
}
@Override
public boolean remove(Object obj){
if(obj == null){
for (int index = 0; index < size; index++) {
if (elementData[index] == null) {
fastRemove(index);
return true;
}
}
}else {
for (int index = 0; index < size; index++) {
if(obj.equals(elementData[index])){
fastRemove(index);
return true;
}
}
}
return false;
}
private void fastRemove(int index) {
//A B C D E 如果index = 2 即移除 C元素
//只需把 D E 整體向前移動一位,A B D E E
// 然後把最後一位置空即可 A B D E null
// step1 算出移動元素的個數
int numMov = size - index - 1;
// step2 如果移動的元素個數大於0,則移動陣列
// 如果移動的元素等於0,則說明刪除的元素是最後一個元素,直接置空即可
if (numMov > 0)
System.arraycopy(elementData, index+1, elementData, index, numMov);
elementData[--size] = null;
}
@Override
public int size() {
return size;
}
}
package com.roger.collection.impl;
import com.roger.collection.RogerList;
import org.junit.Test;
import static org.junit.Assert.*;
public class RogerArrayListTest {
@Test
public void testAdd() {
RogerList<String> rogerArrayList = new RogerArrayList<String>();
rogerArrayList.add("Roger");
rogerArrayList.add("Mary");
rogerArrayList.add("Bruce");
for (int i = 0; i < rogerArrayList.size(); i++) {
System.out.println(rogerArrayList.get(i));
}
}
@Test
public void testAddByPos() {
RogerList<String> rogerArrayList = new RogerArrayList<String>(1);
rogerArrayList.add("Roger");
rogerArrayList.add("Mary");
rogerArrayList.add("Bruce");
rogerArrayList.add(1, "Andy");
for (int i = 0; i < rogerArrayList.size(); i++) {
System.out.println(rogerArrayList.get(i));
}
}
@Test
public void testRemove(){
RogerList<String> rogerArrayList = new RogerArrayList<String>(1);
rogerArrayList.add("Roger");
rogerArrayList.add("Mary");
rogerArrayList.add("Bruce");
rogerArrayList.add(3, "Andy");
rogerArrayList.remove(1);
for (int i = 0; i < rogerArrayList.size(); i++) {
System.out.println(rogerArrayList.get(i));
}
}
@Test
public void testRemoveByObj(){
RogerList<String> rogerArrayList = new RogerArrayList<String>(1);
rogerArrayList.add("Roger");
rogerArrayList.add("Mary");
rogerArrayList.add("Bruce");
rogerArrayList.add(3, "Andy");
rogerArrayList.remove("Andy");
rogerArrayList.remove(null);
for (int i = 0; i < rogerArrayList.size(); i++) {
System.out.println(rogerArrayList.get(i));
}
}
}