编写MyArrayList的基本思路
1.根据ArrayList,MyArrayList需要有clear(),size(),isEmpty(),get(index),set(index ,data),add(data),add(index , data),remove(index)方法。
2.MyArrayList需要提供一个实现Iterator接口的类,这个类current存储迭代序列下一项的下标,并重写hasnext()和next()方法,新增remove()方法,MyArrayList的迭代器方法直接返回实现Iterator接口的类新构造的实例。
3.因为ArrayList是可增的,所以MyArrayList将提供ensureCapacity()方法来改变基础数组的容量,通过新建一个数组来存储原数组的数据,然后将原数组引用给一个新的容量为Capacity的新数组,再将原数组数据拷贝到新数组。
完整代码如下:
package com.MyArrayList;
import java.util.Iterator;
import java.util.NoSuchElementException;
public class MyArrayList<AnyType> implements Iterable<AnyType> {
// 定义初始list大小
// 定义数组
// 定义数组大小
private static final int DEFAULT_CAPACITY = 10;
private AnyType[] theItems;
private int thesize;
// 定义MyArrayList的方法,分别是clear(),size(),get(),set(),isEmpty(),ensureCapaciy(),add(),remove()
// 编写构造函数
public MyArrayList() {
clear();
}
// 清空list
public void clear() {
thesize = 0;
ensureCapacity(DEFAULT_CAPACITY);
}
public int size() {
return thesize;
}
// 判断list是否为空
public boolean isEmpty() {
return size() == 0;
}
// 获取到指定索引的list
public AnyType get(int index) {
if (index < 0 || index > thesize) {
throw new ArrayIndexOutOfBoundsException();
}
return theItems[index];
}
// 将list中索引为index的元素设定为指定元素
public AnyType set(int index, AnyType data) {
if (index < 0 || index > thesize) {
throw new ArrayIndexOutOfBoundsException();
}
AnyType old = theItems[index];
theItems[index] = data;
return old;
}
// 扩充此数组容量,即list容量
@SuppressWarnings("unchecked")
private void ensureCapacity(int newCapacity) {
// 当扩充的容量本身比原list小时
if (newCapacity < size()) {
return;
}
// 创建一个数组保存原数组的数据
AnyType[] old = theItems;
// 将theItem引用给一个新建的容量为newCapacity的数组
theItems = (AnyType[]) new Object[newCapacity];
// 将原数据复制给theItems,
// 注意这里不是old.length而是size(),因为构造函数,所以theItems的大小是10,而size()不一定是
for (int i = 0; i < size(); i++) {
theItems[i] = old[i];
}
}
// 在list尾部新添一个元素
public boolean add(AnyType x) {
add(size(), x);
return true;
}
// 将元素新添到指定索引
private void add(int index, AnyType x) {
if (theItems.length == size()) {
ensureCapacity(size() * 2 + 1);
}
for (int i = thesize; i > index; i--) {
theItems[i] = theItems[i - 1];
}
theItems[index] = x;
thesize++;
}
// 将指定索引index元素移除
public AnyType remove(int index) {
AnyType removedata = theItems[index];
for (int i = index; i < size() - 1; i++) {
theItems[i] = theItems[i + 1];
}
thesize--;
return removedata;
}
public Iterator<AnyType> iterator() {
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator<AnyType> {
public int current = 0;
public boolean hasNext() {
return current < size();
}
public AnyType next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return theItems[current++];
}
public void remove() {
MyArrayList.this.remove(--current);
}
}
}
下面将一一分析其中比较重要的方法:
private static final int DEFAULT_CAPACITY = 10;
private AnyType[] theItems;
private int thesize;
这里定义了一个静态常量 DEAULT_CAPACITY来赋值初始数组大小,theItem则为实现list的容器,thesize为list的大小。
// 编写构造函数
public MyArrayList() {
clear();
}
// 清空list,并将list大小初始化
public void clear() {
thesize = 0;
ensureCapacity(DEFAULT_CAPACITY);
}
// 扩充此数组容量,即list容量
@SuppressWarnings("unchecked")
private void ensureCapacity(int newCapacity) {
// 当扩充的容量本身比原list小时
if (newCapacity < size()) {
return;
}
// 创建一个数组保存原数组的数据
AnyType[] old = theItems;
// 将theItem引用给一个新建的容量为newCapacity的数组
theItems = (AnyType[]) new Object[newCapacity];
// 将原数据复制给theItems,
// 注意这里不是old.length而是size(),因为构造函数,所以theItems的大小是10,而size()大小不一定是。
for (int i = 0; i < size(); i++) {
theItems[i] = old[i];
}
}
这里构造函数调用clear()方法起到的是一个list初始化的作用,通过clea()方法来调用ensureCapacity(DEFAULT_CAPACITY)来将数组清空,因为thesize设为0则在ensureCapacity()方法中拷贝数组的循环不会执行,新数组的所有值自然为空。
private void add(int index, AnyType x) {
if (theItems.length == size()) {
ensureCapacity(size() * 2 );
}
for (int i = thesize; i > index; i--) {
theItems[i] = theItems[i - 1];
}
theItems[index] = x;
thesize++;
}
当list中的元素数量已经达到数组的容量时,则要进行容量扩充,因为扩充容量的大小非常昂贵,所以直接将容量大小扩充一倍。
for循环从thesize,也就是list最后一个元素的后一位,即数组最后一个不为null元素的下一位,然后将前一位数组的元素赋给当前位,循环直到index的后一位,结束循环,再将添加元素赋值给当前索引的数组元素。
public Iterator<AnyType> iterator() {
return new ArrayListIterator();
}
private class ArrayListIterator implements Iterator<AnyType> {
public int current = 0;
public boolean hasNext() {
return current < size();
}
public AnyType next() {
if (!hasNext()) {
throw new NoSuchElementException();
}
return theItems[current++];
}
public void remove() {
MyArrayList.this.remove(--current);
}
}
这里创建了一个ArrayListIterator内部类,实现了Iterable<AnyType>的iterator()方法,返回值为一个新构造的ArrayListIterator实例,这样每个集合可以创建并返回个客户一个实现Itetator接口的对象,并将当前位置的概念在list对象内部存储下来。