实现简单的List功能

简单的实现javaArrayList(可扩容)功能,实现新增,删除,取数据。

package algorithm.data_structure;

/**
 * 模拟ArrayList类的功能
 * @author fangsh
 *
 */
public class SimpleList<T> {
    
    private Object[] elements ;
    
    private int size = 0 ;//记录元素数组的长度
    
    private int elementsNum = 0 ;//记录元素的个数
    
    private final static int ADD_NUMBER = 10 ;//扩容数量
    private final static int RELEASE_CACHE = 5 ;//释放内存的大小
    
    /**
     * 添加元素
     * @param e
     * @return
     */
    public void add(T e){
        if(elements == null) elements = new Object[10] ; // 初始化元素数组,初始化长度为10
        
        if(elements.length <= elementsNum){//判断是否有空间添加元素
            addNumberCache() ;
        }
        elements[elementsNum] = e ;
        
        elementsNum++ ;
    }
    
    /**
     * 删除元素的方法,删除元素时,列表的长度不应该有所改变
     * @param e
     * @return
     * 第一次写方法时犯的错误:对象比较的时候,使用了==,应该使用equals;
     * 需要优化的地方,在删除元素的时候,是否把元素占用的内存释放(涉及长度不够增加的情况)
     */
    public boolean remove(T e){
        if(elements != null){
            if(elements.length > 0){
                int removeIndex = 0 ;
                for(int i=0; i<elements.length; i++){
                    Object obj = elements[i] ;
                    if(obj.equals(e)){
                        removeIndex = i ;
                        break ;
                    }
                }
                Object[] newObject = new Object[elements.length - 1] ;
                for(int begin=0; begin<removeIndex; begin++){
                    newObject[begin] = elements[begin] ;
                }
                for(int continueIndex= removeIndex+1; continueIndex<elements.length; continueIndex++){
                    newObject[continueIndex - 1] = elements[continueIndex] ;
                }
                
                elements = newObject ;
                elementsNum -- ;
                
                return true ;
            }
        }
        return false ;
    }
    
    /**
     * 改进的删除方法,返回删除的元素,并且删除时不修改列表的长度
     * @param t
     * @return
     */
    public T remove2(T t) throws Throwable{
        if(elements == null || isEmpty())
            throw new Throwable("列表为空,或者列表中没有数据") ;
        int removeIndex = -1 ;
        for(int i=0; i<elements.length; i++){
            Object obj = elements[i] ;
            if(obj.equals(t)){
                removeIndex = i ;
            }
            if(removeIndex != -1){
                Object nextElement = null ;
                if(i != elements.length-1)
                 nextElement = elements[i+1] ;
                elements[i] = nextElement ;
            }
        }
        elementsNum -- ;
        if(removeIndex < 0)
            throw new Throwable("删除的元素不在列表内!") ;
        return t ;
    }
    
    public boolean isEmpty(){
        if(elementsNum == 0){
            return true ;
        }
        return false ;
    }
    
    @SuppressWarnings("unchecked")
    public T get(int index) throws Throwable{
        if(elements == null) throw new NullPointerException("列表为空!") ;
        if(index < 0) throw new Throwable("请输入有效的列表下标!") ;
        if(index > elements.length) throw new Throwable("您输入的下标超过列表元素的个数!") ;
        return (T)elements[index-1] ;
    }
    
    /**
     * 扩容的方法,默认扩容的长度为10
     */
    private void addNumberCache(){
        if(elements == null) return ;
        if(elements.length == elementsNum){
            Object[] newElements = new Object[elementsNum + ADD_NUMBER] ;
            for(int i=0; i<elements.length; i++){
                newElements[i] = elements[i] ;
            }
            elements = newElements ;
        }
    }
    
    /**
     * 当SimpleList中的空余内存达到一定数量时,释放SimpleList中的内存
     */
    private void releaseNumberCache(){
        if(elements == null) return ;
        if(elements.length > (elementsNum + 10)){//达到释放标准
            Object[] newElements = new Object[elements.length - RELEASE_CACHE] ;
            for(int i=0; i<(elements.length - RELEASE_CACHE); i++){
                newElements[i] = elements[i] ;
            }
            elements = newElements ;
        }
    }
    
    /**
     * 查询列表元素的个数
     * @return
     */
    public int getElementNum(){
        return elementsNum;
    }
    
    /**
     * 查询元素列表的长度
     * 注意这个方法一定不能用来判断列表元素的个数,因为列表可能存在多余空间
     * @return
     */
    public int getSize() throws Throwable{
        if(elements == null)
            throw new Throwable("列表为空!") ;
        return elements.length ;
    }
}

总结一下,做这个时出现的一些问题,日后注意:

1、在对比对象的时候,一开始脑残的使用了“==” ,导致删除方法不成功,对象比较注意一定使用equals方法。

 

2、做删除元素的时候,将元素数组的长度减少了,没有更新size这个字段,这个字段可以不用,需要这个值的时候,直接调用数组的length方法,减少bug出现的可能性(要随时同步size这个值,增加了出bug的可能性)

 

3、一开始的删除方法,会新建一个数组,并且还要重新遍历原素组,将元素重新加入到新数组中,这样造成资源的浪费,可以直接将被删除元素之后的元素依次往前移,最后一个数组位置补null。这样避免了新建数组造成的资源开销。

posted on 2016-06-23 17:04  狂野的小怪兽  阅读(322)  评论(0编辑  收藏  举报