0.1)查询效率高:在其内部有下标,即有索引,直接就可以取到数据
0.2) 删除慢:因为需要将当前后面的数据往前移动移位,这时会用到数据扩容技术,这样效率非常低
1.1 无参构造函数,默认一个空数组
1.2 带容量的有参构造函数:根据容量参数的值范围来初始化
1.3 源码中数组默认的初始容量为 :10
1.4 源码中数组默认的最大容量为:Integer.MAX_VALUE - 8
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.1 数组越界检查,即指定位置是否越界 (index允许的范围是 [0,size])
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.1 数组越界检查 (index允许的范围是 [0,size))
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.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;
}
package com.roger.collection;
public interface RogerList {
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 implements RogerList {
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 rogerArrayList = new RogerArrayList();
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 rogerArrayList = new RogerArrayList(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 rogerArrayList = new RogerArrayList(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 rogerArrayList = new RogerArrayList(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));
}
}
}