手写ArrayList

ArrayList是Java中最为简单也是最为常用的一个容器,那么它的内部构造是什么呢?其实ArrayList的底层实现就是数组,它的各种方法就是对数组进行的一系列操作,例如对数组元素的修改,删除,位移,对数组长度的获取等。我们可以手写一个ArrayList容器,以助我们更好的理解这个容器:

package Collection;

import java.util.Iterator;
/**
 * 深入迭代器的原理-->一个容器可以创建多个迭代器对象
 * 1.使用了内部类,实现迭代器
 * 2.使用Iterable实现foreach迭代
 * @author XieHuazhen
 *
 */

//实现Iterable接口是为了能够多一种遍历容器的方法:增强for循环
public class MyArrayList<E> implements Iterable<E>{ 

    //数组存储值
    private Object[] elemData;
    //容器大小
    private int size;

    private boolean rangeCheck(int index) {
        if(index<0||index>=size) {
            try {
                throw new IllegalArgumentException();
            }catch(IllegalArgumentException e) {
                e.printIndex();
            }
        }
        return true;
    }

    private void ensureCapacity() {
        if(size>=elemData.length) {
            Object[] newElem = new Object[size*2+1];
            System.arraycopy(elemData,0,newElem,0,elemData.length);
            elemData = newElem;
        }
    }

    public MyArrayList (int initCapacity){
        if(initCapacity>=0) {
            elemData = new Object[initCapacity];
        }else {
            try {
                throw new IllegalArgumentException();
            }catch(IllegalArgumentException e) {
                e.printCapacity();
            }
        }
    }

    public MyArrayList() {
        this(0);
    }

    public boolean isEmpty() {
        return size==0;
    }

    public boolean contains(Object o) {
        return indexOf(o)>=0;
    }

    public int indexOf(Object o) {
        for(int i=0;i<size;++i) {
            if(elemData[i].equals(o))
                return i;
        }
        return -1;
    }

    @SuppressWarnings("unchecked")
    public E elemData(int index) {
        return (E)elemData[index];
    }

    public E set(int index,Object o) {
        rangeCheck(index);
        E oldElem = elemData(index);
        elemData[index] = o;
        return oldElem;
    }

    public E get(int index) {
        rangeCheck(index);
        return elemData(index);
    }

    public void add(Object o) {
        ensureCapacity();
        elemData[size++] = o;
    }

    public void add(int index,Object o) {
        rangeCheck(index);
        ensureCapacity();
        System.arraycopy(elemData,index,elemData,index+1,size-index);
        elemData[index] = o;
        ++size;
    }

    public E remove(int index) {
        rangeCheck(index);
        E oldElem = elemData(index);
        System.arraycopy(elemData,index+1,elemData,index,size-index-1);
        elemData[--size] = null;
        return oldElem;
    }

    public boolean remove(E e) {
        for(int i=0;i<size;++i) {
            if(e.equals(elemData[i])) {
                remove(i);
                return true;
            }
        }
        return false;
    }

    //使用内部类定义iterator()
    public Iterator<E> iterator(){
        return new MyItr();
    }

    private class MyItr implements Iterator<E>{

        //计数器-->指针 游标
        private int cursor = 0;
        private int lastRet = -1;

        //判断是否存在下一个
        public boolean hasNext() {
            return cursor!=size;
        }

        //返回游标当前位置,并把游标移到下一位置
        @SuppressWarnings("unchecked")
        public E next() {
            if(!hasNext()) {
                try {
                    throw new IllegalArgumentException();
                }catch(IllegalArgumentException e) {
                    e.printNext();
                }
            }
            lastRet = cursor;
            return (E) elemData[cursor++];
        }

        //删除游标左面元素,执行完next后只能执行一次
        public void remove() {
            if(lastRet<0) {
                try {
                    throw new IllegalArgumentException();
                }catch(IllegalArgumentException e) {
                    e.printRemove();
                }
            }
            System.arraycopy(elemData,lastRet+1,elemData,lastRet,size-lastRet-1);
            cursor = lastRet;
            lastRet = -1;
            elemData[--size] = null;
        }
    }
    public static void main(String[] args) {

        MyArrayList<String> list = new MyArrayList<>();
        list.add("abc");
        list.add("def");
        list.add("ghi");
        list.add("jkl");

        //使用迭代器遍历
        for(Iterator<String> itr=list.iterator();itr.hasNext();) {
            System.out.println(itr.next());
            //itr.remove();
        }

        System.out.println("---------------------");

        //使用增强for循环遍历
        for(String str:list) {
            System.out.println(str);
        }
    }
}
package Collection;

public class IllegalArgumentException extends Exception{

    private static final long serialVersionUID = 1L;

    public void printCapacity() {
        System.out.println("异常,初始容量参数不合法");
        System.exit(1);
    }

    public void printIndex() {
        System.out.println("异常,索引范围不合法");
        System.exit(1);
    }

    public void printNext() {
        System.out.println("异常,无法返回当前位置元素");
        System.exit(1);
    }

    public void printRemove() {
        System.out.println("异常,无法移除");
        System.exit(1);
    }
}

原文地址:https://www.cnblogs.com/xiehuazhen/p/8535497.html

时间: 2024-10-10 19:57:36

手写ArrayList的相关文章

1 手写ArrayList核心源码

手写ArrayList核心源码 ArrayList是Java中常用的数据结构,不光有ArrayList,还有LinkedList,HashMap,LinkedHashMap,HashSet,Queue,PriorityQueue等等,我们将手写这些常用的数据结构的核心源码,用尽量少的代码来揭示核心原理. 下面我们来手写ArrayList的核心源码 首先我们定义一个QArrayList,不要问为什么叫QArrayList,因为我之前写过Qt,仅此而已.源码 public class<T> QAr

android项目 之 记事本(7)----- 手写功能之删除、恢复和清空

上一节,为记事本添加了手写的功能,但是没有实现底部按钮的各种功能,这节就先实现撤销,恢复和清空的功用. 因为不会录制屏幕成gif图片,所以就以图片形式给出吧,不是很形象,凑合着看: 显然,需要为底部GridView的添加item单击事件: private GridView paint_bottomMenu; paint_bottomMenu = (GridView)findViewById(R.id.paintBottomMenu); paint_bottomMenu.setOnItemClic

android手写笔思路

工作需要,对这方面做了一些了解 一般的手写对android canvas有点理解的应该都知道,只需要单纯的使用drawPath就可以在view上画画. 而手写笔的关键则是要让path的strokeWidth发生变化 这个令人头大了, 毕竟setPaint只能够设置一个paint,一旦改变paint的参数,整个path都会发生改变. 所以,我们只能够另辟蹊径. 我们可以先开一个arraylist(Point),用来记录我们在surfaceview(推荐在画画功能上使用surfaceview代替vi

Android 手写Binder 教你理解android中的进程间通信

关于Binder,我就不解释的太多了,网上一搜资料一堆,但是估计还是很多人理解的有困难.今天就教你如何从 app层面来理解好Binder. 其实就从我们普通app开发者的角度来看,仅仅对于android应用层的话,Binder就是客户端和服务端进行通信的媒介. AIDL就是我们理解Binder 最好的事例. 我们都知道 我们写好aidl 文件以后,开发工具 会自动帮我们生成好代码.实际上 我们最终apk里面 是只有这些代码的,我们写的aidl文件 是不会被打包进去的,也就是说aidl文件 实际上

手写阻塞队列(Condition实现)

自己实现阻塞队列的话可以采用Object下的wait和notify方法,也可以使用Lock锁提供的Condition来实现,本文就是自己手撸的一个简单的阻塞队列,部分借鉴了JDK的源码.Ps:最近看面经的时候发现字节跳动的面试官特别喜欢让面试者手写阻塞队列,希望本文能对大家有帮助.个人手撸如有错误还请批评指正. public class AxinBlockQueue { //队列容器 private List<Integer> container = new ArrayList<>

跟我一起造轮子 手写springmvc

作为java程序员,项目中使用到的主流框架多多少少和spring有关联,在面试的过程难免会问一些spring springmvc spring boot的东西,比如设计模式的使用. 怎么实现springioc 怎么实现springmvc诸如此类的问题,今天我们就来探寻spring mvc的实现,然后自己实现一个简单的spring mvc 一. 了解spring mvc的基本运行流程 ps: 网上一大堆关于springmvc的详细讲解,在这里就不累赘了 小结:spring mvc的核心是Dispa

手写Tomcat服务器

预备知识 编写服务器用到的知识点 1) Socket 编程2) HTML3) HTTP 协议4) 反射5) XML 解析6) 服务器编写 Socket编程 https://www.cnblogs.com/bfcs/p/10790130.html HTML知识 HTML:HyperText Markup Language 超文本标记语言用于描述网页文档的一种标记语言 表单(form):与用户之间进行交互 method:请求方式 get/post get 数据量小,安全性低,默认方式 post 数据

了解mybatis源码手写mybatis

一:mybatis概述 MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简单的 XML 或注解来配置和映射原生信息,将接口和 Java 的 POJOs(Plain Ordinary Java Object,普通的 Java对象)映射成数据库中的记录. 二:手写mybatis 实现思路:: 1创建SqlSessionFactory实例 2:实例化过程中,加载配置

手写MyBatis ORM框架实践

一.实现手写Mybatis三个难点 1.接口既然不能被实例化?那么我们是怎么实现能够调用的? 2.参数如何和sql绑定 3.返回结果 下面是Mybatis接口 二.Demo实现 1.创建Maven工程(开发工具Eclipse) 下一步 下一步 然后点击“完成” 2.配置pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema