关于如何查看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);
}
}
}