数据结构—顺序表(自己实现Java的ArrayList)

数据结构按逻辑划分为两大类:1. 线性结构

1) 顺序表(顺序存储)  2) 链表(链式存储)  3) 栈  4) 队列  5) 串

2. 非线性结构 

1) 树  2) 图

众所周知,数组是最简单的顺序表。 然而在Java 的世界里,提供了一个集合体系,这个集合体系工具是为了方便Java 开发者在内存级(数据结构就是在数据再内存中的组织方式)组织数据,以便帮助开发者快速编写出高效优质的的代码。在JDK 7.0 中有4大集合体系: 1) List体系  2) Set体系  3) Map体系  4) Queue体系(jdk 7.0新增)。

好,理论够多了,现在开始来实现最简单的 ArrayList 吧! (可别小看这个ArrayList, 查看JDK源码你就会发现它比你想象中的强大,那些都是大师级智慧的结晶呀,多看看这些源代码对我们的编程水平绝对有质的飞跃!) 笔者不才,即使这个最简单的顺序表ArrayList,在参考jdk源码的情况下我也写了将近3个晚上,而且迭代功能还没实现。惭愧! 本人自己实现ArrayList源码如下: 有不妥之处,还望高手指正! Java源码里的数据结构与算法我将打算逐个自己实现,希望遇到高手指导下我这个菜鸟。

package sequenceList;

import java.util.Arrays;


/**
 * 这是一个线性表的顺序存储结构,即顺序表。 这个类是一个顺序表数据结构的一般实现。
 * 
 * @version 1.0
 * @start_time 2013-06-07
 * @end_time 2013-06-09
 * @author whw
 * @param <E>
 * 
 */
public class ArrayList<E> implements java.io.Serializable{

	private static final long serialVersionUID = 1L;
	
	/**
	 * 定义一个顺序结构的允许最大容量,这里参考了jdk源码的方法,官方文档解释说
	 * Object[]的最大容量一般收到VMs的限制,推荐设置为Integer.MAX_VALUE-8
	 */
	private static final int MAX_SIZE = Integer.MAX_VALUE-1; 
	
	/**
	 * 这个变量是保存着ArrayList的大小
	 */
	private int size;
	
	/**
	 * 这个变量保存ArrayList的实际存储长度,这个长度不一定等于初始化大小。 
	 * 而是实际存储了数据的长度。
	 */
	private int currentSize = -1;
	
	/**
	 * 这是一个存放ArrayList的数据的对象数组
	 */
	private Object[] elementData; 
	
	/**
	 * 默认初始化方法,在jdk源码里 默认初始化方法时 默认设置Object的初始大小为10 
	 * 这里的实现也参考了jdk源码的初始化设置
	 */
	
	public ArrayList(){
		this(10);
	}
	
	/**
	 * ArrayList初始化构造器,这个初始化方法要求使用者指定构造该ArrayList的初始化大小initCapacity.
	 * @param initCapacity 初始化容量
	 */
	public ArrayList(int initCapacity){
		if(initCapacity < 0)
			throw new ExceptionInInitializerError();
		if(initCapacity > MAX_SIZE)	
			throw new ArrayIndexOutOfBoundsException();
		
		this.elementData = new Object[initCapacity]; // 初始化数组
		this.size = initCapacity; // 同时初始化ArrayList的大小
	}
	
	/**
	 * 确保所需的ArrayList容量没有超过初始化的容量
	 * @param requireCapacity 所需的容量
	 */
	private void ensureCapacity(int requireCapacity){
		if(requireCapacity < 0)
			throw new ExceptionInInitializerError();
		if(requireCapacity >= this.size){
			int newCapacity = requireCapacity+10;  // 每次扩展容量只扩展10个单位的容量。
			if(newCapacity > MAX_SIZE){
				newCapacity = requireCapacity + (10 - (newCapacity - MAX_SIZE)); // 重新计算新的容量
			}
			this.size = newCapacity;
			elementData = Arrays.copyOf(elementData, newCapacity);		
		}
	}
	
	/**
	 * 获得顺序表ArrayList的容量
	 * @return int
	 */
	public int getSize(){
		return this.size;
	}
	
	/**
	 * 获得顺序表ArrayList的实际存储大小
	 * @return int
	 */
	public int getCurrentSize(){
		return this.currentSize+1;
	}
	
	/**
	 * 判断顺序表ArrayList是否为空
	 * @return boolean
	 */
	public boolean isEmply(){
		return (this.currentSize==-1);
	}
	
	/**
	 * 增加泛型的支持,使每个放入ArrayList容器的元素不会丢失其数据类型
	 * @param index
	 * @return E
	 */
    @SuppressWarnings("unchecked") 
    private E elementData(int index) {
    	checkRange(index);
    	
        return (E) elementData[index];
    }
    
	/**
	 * 往顺序表ArrayList尾部添加元素的方法。
	 * @param e 要添加的元素
	 */
	public boolean add(E e){
		ensureCapacity(currentSize+1);
		elementData[currentSize+1] = e;
		currentSize++; // 更新顺序表实际存放数据的大小
		return true;
	}
	
	/**
	 * 往顺序表ArrayList指定位置添加元素的方法。
	 * @param e 要添加的元素
	 * @param index 要添加到顺序表里的位置索引
	 */
	public boolean addAtIndex(E e, int index){
		checkRange(index);
		
		ensureCapacity(currentSize+1);
		
		for(int i=currentSize; i>=index; i--){
			elementData[i+1] = elementData[i];
		}
		elementData[index] = e;
		currentSize++; // 更新顺序表实际存放数据的大小
		return true;
	}
	
	/**
	 * 删除指定索引位置的ArraList里的元素
	 * @param index 要删除的元素的索引
	 * @return boolean
	 */
	public boolean removeByIndex(int index){
		checkRange(index);
		
		elementData[index] = null;
		currentSize--; // 顺序表长度减一
		return true;
	}
	
	/**
	 * 删除指定ArraList里的元素
	 * @param e 要删除的元素
	 * @return boolean
	 */
	public boolean removeByElement(E e){
		int index = indexOf(e);
		elementData[index] = null;
		currentSize--; // 顺序表长度减一
		return true;
	}
	
	/**
	 * 删除所有ArraList里的元素
	 * @return boolean
	 */
	public boolean removeAll(){
		for(int i=0; i<currentSize; i++){
			elementData[i] = null;
		}
		currentSize = -1;
		return true;
	}
	
	/**
	 * 获取指定索引位置的ArrayList里的元素
	 * @param index 要获取的元素的索引
	 * @return E
	 */
	public E get(int index){
		return (elementData(index));
	}
	
	/**
	 * 替换指定位置的元素
	 * @param e 要替换的元素
	 * @param index  要替换的元素的索引
	 * @return boolean 返回true表示替换成功,返回false则相反
	 */
	public boolean replaceByIndex(E e, int index){
		checkRange(index);
		elementData[index] = e;
		return true;
	}
	
	/**
	 * 替换指定的元素
	 * @param e1 替换前的元素
	 * @param e2  替换后的元素
	 * @return boolean 返回true表示替换成功,返回false则相反
	 */
	public boolean replaceByElement(E e1, E e2){
		if(e1.getClass() != e2.getClass())
			throw new ClassCastException();
		int index = indexOf(e1);
			elementData[index] = e2;
		return true;
	}
	
	/**
	 * 搜索指定元素是否包含在ArrayList里
	 * @param e 要搜索元素
	 * @return boolean  返回true表示ArrayList中包含指定元素,返回false则相反。
	 */
	public boolean contains(Object e){
		return indexOf(e) != -1;
	}
	
	/**
	 * 搜索指定元素在ArrayList里的索引位置
	 * @param e 要搜索元素
	 * @return int 返回该元素所在的索引,没有返回-1
	 */
	public int indexOf(Object e){
		if(e==null || e=="" || e.equals(null) || e.equals(""))
			return -1;
		else {
			for(int i=0; i<=currentSize; i++)
				if(e.equals(elementData[i]) || e.hashCode()==elementData[i].hashCode())
					return i;
			}
		return -1;
	}
	
	/**
	 * 判断索引的范围
	 * @param index 需要判断的索引
	 */
	private void checkRange(int index){
		if(index<0 || index>currentSize)
			throw new ArrayIndexOutOfBoundsException();
	}
	
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值