本篇介绍手动实现一个ArrayList的基本功能。
ArrayList的底层是一个动态数组,这个有别于LinkedList的链表。代码实现了ArrayList的基本功能,所以没有实现ArrayList实现的一些接口,比如:RandomAccess和Serializable等。
方法名 | 作用 |
getSize() | 获取数组大小 |
checkIncrease(int index,Object obj) | 扩容,将原来的数组扩容一倍并将原来数据拷贝到新数组 |
indexOf(Object o) | 根据元素获取在数组中首次出现的索引值 |
add(Object o) | 往数组中添加元素 |
remove(int index) | 删除数组中的元素如果此元素不在数组最后位置则将其后面的每个元素向前移动一位 |
checkIndexOut(int index) | 检查所给下标是否越界 |
get(int index) | 获取指定下标数据 |
removeAll() | 清空数组 |
change(int index,Object o) | 修改对应索引的值 |
contains(Object o) | 判断是否包含对应值 |
isEmpty() | 判断是否为空 |
public class MyArrayList {
//用于存储数据
private Object[] data = null;
//集合的元素个数
private int size = 0;
//定义一个常量为 10.(后面用于定义默认的集合大小)
private static final int DEFAULT_CAPACITY = 10;
/**
* 无参构造函数,指定初始大小为10
*/
public MyArrayList(){
this(DEFAULT_CAPACITY);//调用有参构造函数
}
/**
* 有参构造函数,指定数组大小
* @param initialCapacity
*/
public MyArrayList(int initialCapacity){
if(initialCapacity < 0){//判断数组大小不嗯呢该为负数
throw new IllegalArgumentException("非法的集合初始容量值 Illegal Capacity: "+initialCapacity);
}else{
//实例化数组
this.data = new Object[initialCapacity];
}
}
/**
* 获取数组大小
* @return
*/
public int getSize(){
return size;
}
/**
* 扩容,复制原来的数组并扩容一倍
* @param index
* @param obj
*/
public void checkIncrease(int index,Object obj){
if(size >= data.length){//原来数组放满之后进行扩容
//实例化一个新数组
Object[] newData = new Object[size*2];
if(index == -1 && obj == null){
System.arraycopy(data, 0, newData, 0, size);
}else{
//将要插入索引位置前面的对象 拷贝
System.arraycopy(data, index, newData, index+1, size-index);
}
data = newData;
newData = null;
}
}
/**
* 根据元素获得在集合中首次出现的索引
* @param o
* @return
*/
public int indexOf(Object o){
if(o == null){
for(int i = 0,len=data.length;i<len;i++){
if(data[i] == null){
return i;
}
}
}else{
for(int i=0,len=data.length;i<len;i++){
if(o.equals(data[i])){
return i;
}
}
}
return -1;
}
/**
* 在尾部添加元素
* @param o 需要被添加的元素
*/
public boolean add(Object o){
//检查是否需要扩容
checkIncrease(-1,null);
data[size++] = o;
return true;
}
/**
* 根据索引删除元素
* @param index
* @return
*/
public boolean remove(int index){
if(checkIndexOut(index)){//判断数组是否越界
if(index == size-1){//如果要删除的元素为最后一个元素
data[index] = null;
}else{//如果删除的元素不为最后一个元素则需要将此元素之后的元素向前移一位
System.arraycopy(data,index+1,data,index,size-index);
}
size--;
return false;
}else{//数组越界情况
throw new IndexOutOfBoundsException("指定的索引越界,集合大小为:"+size+",您指定的索引大小为:"+index);
}
}
/**
* 判断给定索引是否越界
* @param index
* @return
*/
public boolean checkIndexOut(int index){
if(index >= size || index <0){
// throw new IndexOutOfBoundsException("指定的索引越界,集合大小为:"+size+",您指定的索引大小为:"+index);
return false;
}
return true;
}
/**
* 根据给定索引获取元素
* @param index
* @return
*/
public Object get(int index) {
checkIndexOut(index);//判断是否越界
return data[index];
}
/**
* 删除所有元素
*/
public void removeAll(){
for(int i=0,len=data.length;i<len;i++){
data[i] = null;
}
size = 0;//
}
/**
* 根据索引修改元素
* @param index
* @param o
* @return
*/
public boolean change(int index,Object o){
checkIndexOut(index);//判断是否越界
data[index] = o;
return true;
}
/**
* 判断某个元素是否存在,若存在则返回索引,不存在返回-1
* @param o
* @return
*/
public int contains(Object o){
for(int i = 0,len=data.length;i<len;i++){
if(o.equals(data[i])){
return i;
}
}
return -1;
}
/**
* 判断数组是否为空
* @return
*/
public boolean isEmpty() {
return size == 0;
}
}