数据结构之ArrayList的简单实现


关于如何查看java里面各个类的源代码,参考这里:http://blog.csdn.net/qq_27857857/article/details/71250401


1.介绍

ArrayList是java集合中一个经常用到的类,它最方便的地方就在于可以自动扩容和支持泛型。

下面我们将会模拟实现ArrayList中的一些方法,比如增加、删除、扩容、迭代器等。


2.MyArrayList

我们将自己的类叫做MyArrayList,为了和java自带的ArrayList区分开。

3.实现

3.1 类的名称、实现的接口以及泛型支持

public class MyArrayList<AnyType> implements Iterable<AnyType>{

}

我们自己的类需要实现Iterable 接口,提供迭代器遍历这个集合。如果不了解迭代器的,不实现这个接口也没关系。


3.2  类的数据成员

private static final int DEFAULT_CAPACITY = 5;
private int theSize;
private AnyType[] theItems;

三个数据成员分别表示 默认容量、存放的数据个数、存放数据的数组;


3.3 构造方法

public  MyArrayList() {
theSize = 0;
ensureCapacity(DEFAULT_CAPACITY);
}

这里初始化theSize = 0, ensureCapacity方法就是扩容的方法,在这里用来初始化存放数据的数组。


3.4 得到集合大小

public int size(){
return theSize;

}

3.5 get、set方法

public AnyType get(int idx){
if(idx < 0 || idx>=size())
throw new ArrayIndexOutOfBoundsException();
return theItems[idx];
}

public AnyType set(int idx,AnyType newVal){
if(idx < 0 || idx>=size())
throw new ArrayIndexOutOfBoundsException();

AnyType old = theItems[idx];
theItems[idx] = newVal;
return old;
}

逻辑很简单,就是返回数组中的某个元素。


3.6 add方法和ensureCapacity方法

public void add(int idx,AnyType x){
if(theItems.length == size())
ensureCapacity(size()* 2 +1);
for(int i = theSize;i>idx;i--)
theItems[i] = theItems[i-1];
theItems[idx]=x;

theSize++;
}

add方法参数表示在idx位置插入x这个元素。

第一个if判断是否需要扩容,当length==size的时候,说明数组没有空间存放数据了,就调用ensureCapacity方法扩容。

for循环就是把idx后面的元素依次后移,把idx这个位置腾空 。

下面看扩容的方法ensureCapacity

public void ensureCapacity(int newCapacity){
if(newCapacity < theSize)
return;
if(theItems ==null)
{
theItems = (AnyType[]) new Object[DEFAULT_CAPACITY];
return;
}
Class any =  theItems.getClass();
Class component = any.getComponentType();
Object newArray = Array.newInstance(component, newCapacity);
System.arraycopy(theItems, 0, newArray, 0, theSize);
theItems =(AnyType[]) newArray;
}

这里theItems ==null 判断是否是第一次初始化数组(之前没初始化的话theItems就是null,后面的getClass就有空指针异常)。

后面的几行代码就是扩容的方法了,就是 创建一个容量更大的新数组,再把原来的元素复制到新数组里。

Class any =  theItems.getClass();得到数组的Class对象

Class component = any.getComponentType(); 得到数组中 保存的元素的类型。

Object newArray = Array.newInstance(component, newCapacity); 创建一个和原来theItems保存类型一样的数组,只是这数组容量更大。

可以想象成 new AnyType[newLength],

最后System.arraycopy 就是把原来数组的东西复制到新数组里,这个方法是java自带的。


这里扩容的具体实现大家不一定要我这么做,可以用别的方法实现,比如结合Arrays.copyOf()和System.arrayCopy(),或者直接(AnyType[])new Object[newLength],  关键是 创建一个保存AnyType类型,容量更大的数组。


3.7 add方法

public boolean add(AnyType x){
add(size(),x);
return true;

}

没有指定位置的add方法,就把元素添加在数组的最后面。


3.8 remove方法

public AnyType remove(int idx){
if(idx < 0 || idx>=size())
throw new ArrayIndexOutOfBoundsException();

AnyType removeItem = theItems[idx];
for(int i=idx;i<size()-1;i++)
theItems[i] = theItems[i+1];

theSize--;
return removeItem;
}

有点类似于add方法,for循环用来移动元素,因为把某个位置的元素删掉后,这个位置就空闲了,要把后面的元素依次前移。


3.9迭代器的实现类(内部类)

private class ArrayListIterator implements Iterator<AnyType>{


private int current =0;


@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return current < size();
}


@Override
public AnyType next() {
// TODO Auto-generated method stub
if(!hasNext())
throw new NoSuchElementException();
return theItems[current++];
}
public void remove(){
MyArrayList.this.remove(--current);
}

}

这里用了内部类实现迭代器,内部类可以访问外部类的各个数据成员和方法。不太了解的可以去搜索内部类相关的知识。

4.0取得迭代器

@Override
public Iterator<AnyType> iterator() {
// TODO Auto-generated method stub
return new ArrayListIterator();
}
新建
一个内部类对象并返回。


5.总结

这里只是实现了ArrayList的少部分方法

能实现这些方法,那大家也可以自己去实现get、add、remove等多种重载版本了,还有一些其他没实现的方法大家可以查阅java源代码里面的Collection接口,看看这个接口规定了哪些方法 然后在MyArrayList里面实现试试。

关于如何查看java里面各个类的源代码,参考这里:http://blog.csdn.net/qq_27857857/article/details/71250401



下面是整个类的代码:

package ArrayList模拟实现;


import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Iterator;
import java.util.NoSuchElementException;


public class MyArrayList<AnyType> implements Iterable<AnyType>{



private static final int DEFAULT_CAPACITY = 5;
private int theSize;
private AnyType[] theItems;
public  MyArrayList() {
// TODO Auto-generated constructor stub
doClear();
}
public void clear(){
doClear();
}

private void doClear(){
theSize = 0;
ensureCapacity(DEFAULT_CAPACITY);

}
public int size(){
return theSize;

}
public int realLenth(){
return theItems.length;
}
public boolean isEmpty(){

return size()==0;

}
public void trimToSize(){
ensureCapacity(size());
}
public AnyType get(int idx){
if(idx < 0 || idx>=size())
throw new ArrayIndexOutOfBoundsException();
return theItems[idx];
}

public AnyType set(int idx,AnyType newVal){
if(idx < 0 || idx>=size())
throw new ArrayIndexOutOfBoundsException();

AnyType old = theItems[idx];
theItems[idx] = newVal;
return old;
}

public void ensureCapacity(int newCapacity){
if(newCapacity < theSize)
return;
if(theItems ==null)
{
theItems = (AnyType[]) new Object[DEFAULT_CAPACITY];
return;
}
Class any =  theItems.getClass();
Class component = any.getComponentType();
Object newArray = Array.newInstance(component, newCapacity);
System.arraycopy(theItems, 0, newArray, 0, theSize);
theItems =(AnyType[]) newArray;
}
public boolean add(AnyType x){
add(size(),x);
return true;

}
public void add(int idx,AnyType x){
if(theItems.length == size())
ensureCapacity(size()* 2 +1);
for(int i = theSize;i>idx;i--)
theItems[i] = theItems[i-1];
theItems[idx]=x;

theSize++;
}
public AnyType remove(int idx){
if(idx < 0 || idx>=size())
throw new ArrayIndexOutOfBoundsException();

AnyType removeItem = theItems[idx];
for(int i=idx;i<size()-1;i++)
theItems[i] = theItems[i+1];

theSize--;
return removeItem;
}

public String printAll(){
String s = Arrays.toString(theItems);
return s;
}

@Override
public Iterator<AnyType> iterator() {
// TODO Auto-generated method stub
return new ArrayListIterator();
}



private class ArrayListIterator implements Iterator<AnyType>{


private int current =0;


@Override
public boolean hasNext() {
// TODO Auto-generated method stub
return current < size();
}


@Override
public AnyType next() {
// TODO Auto-generated method stub
if(!hasNext())
throw new NoSuchElementException();
return theItems[current++];
}
public void remove(){
MyArrayList.this.remove(--current);
}

}


}

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值