package cn.yangwanhao.collection.list;
import java.util.Iterator;
import java.util.NoSuchElementException;
/**
* Title: MyArrayList类<br>
* Description: 模仿ArrayList和Iterator
* Company: 卓瀛工作室
*
* @author 杨万浩
* @version 1.0
*/
public class MyArrayList<E> implements Iterable<E> {
/**
* 初始化数组容量为10
*/
private static final int DEFAULT_CAPACITY = 10;
/**
* 集合的长度
*/
private int theSize;
/**
* 集合体
*/
private E [] theItems;
/**
* 构造方法,初始化数组
*/
public MyArrayList() {
doClear();
}
/**
* 对外提供的初始化数组的方法
*/
public void clear() {
doClear();
}
/**
* 初始化数组的方法
*/
private void doClear() {
//把数组大小设为0
theSize = 0;
ensureCapacity(DEFAULT_CAPACITY);
}
/**
* 提供集合大小的方法
* @return 数组的大小
*/
public int size() {
return theSize;
}
/**
* 判断集合是否为空
* @return 数组的大小是否为0
*/
public boolean isEmpty() {
return theSize==0;
}
/**
* 把数组多余的部分切掉
*/
public void trimToSize() {
ensureCapacity(size());
}
/**
* 数组扩容
* @param newCapacity 新的数组大小
*/
private void ensureCapacity(int newCapacity) {
//如果新的容量比现有的容量还小,直接返回
if(newCapacity < theSize) {
System.out.println(newCapacity + " < " + theSize);
return;
}
//获取旧的数组体
E [] old = theItems;
//新建一个数组
theItems = (E []) new Object[newCapacity];
//把旧的数组copy过去
for(int i=0; i<size(); i++) {
theItems[i] = old[i];
}
}
/**
* 获取集合中特定位置的值
* @param idx 值在集合中的位置
* @return 该位置的元素
*/
public E get(int idx) {
if (idx < 0 || idx >= size()) {
throw new ArrayIndexOutOfBoundsException();
}
return theItems[idx];
}
/**
* 修改集合中某个特定位置的元素
* @param idx 要修改的元素在集合中的位置
* @param newVal 要修改的元素的新值
* @return 返回旧的元素(被替换掉的元素)的值
*/
public E set(int idx, E newVal) {
if(idx < 0 || idx >= size()) {
throw new ArrayIndexOutOfBoundsException();
}
E old = theItems[idx];
theItems[idx] = newVal;
return old;
}
/**
* 添加一个元素到集合尾部
* @param val 要添加的元素
* @return 添加成功
*/
public boolean add(E val) {
add(size(), val);
return true;
}
/**
* 添加元素到指定位置
* @param idx 位置
* @param val 元素的值
*/
public void add(int idx ,E val) {
//如果数组的容量已经满了,就进行扩容
if(theItems.length == size()) {
ensureCapacity(size()+(size()>>1));
}
//把idx位置后边的值依次往后挪一位,腾出idx那个位置
for(int i=theSize; i>idx; i--) {
theItems[i] = theItems[i-1];
}
//赋值
theItems[idx] = val;
//集合长度+1
theSize++;
}
/**
* 删除集合中特定位置的一个元素
* @param idx 位置
* @return 删除的那个元素
*/
public E remove(int idx) {
//得到那个要被删除的元素
E removeItem = theItems[idx];
//把该位置元素之后的元素依次向前挪一位
for (int i=idx; i<size()-1; i++) {
theItems[i] = theItems[i+1];
}
//集合长度-1
theSize--;
return removeItem;
}
/**
* Returns an iterator over elements of type {@code T}.
* @return an Iterator.
*/
@Override
public Iterator<E> iterator() {
return new MyArrayListIterator();
}
private class MyArrayListIterator implements Iterator<E> {
private int current = 0;
@Override
public boolean hasNext() {
return current<size();
}
@Override
public E next() {
if(!hasNext()) {
throw new NoSuchElementException();
}
return theItems[current++];
}
@Override
public void remove() {
MyArrayList.this.remove(--current);
}
}
}
ArrayList底层使用数组完成。创建时初始化一个数组长度。每次执行添加操作时先查询数组里是否还有空间,如果有就添加,如果没有,则进行扩容操作。扩容就是先获取旧的数组,再创建一个新的数组,初始化它的长度为原数组的1.5倍,再把旧数组的内容拷贝过去。由于每次(在表前或者中间)添加或者删除一个元素都需要挪动后边的元素,所以ArrayList的添加或者删除的效率很低。但是数组根据下标来查询或者修改某个特定的元素时时间复杂度为O(1),所以它的查询很快。至于遍历......他们都是从前往后一个一个遍历,和LinkedList倒是相差无几。
来源:https://www.cnblogs.com/yangwanhao/p/10675800.html