当前位置: 首页 > news >正文

ArrayList的实现

ArrayList实现

  本文给出ArrayList的简单实现,ArrayList内部采用数组实现,因此具有较快的元素访问速度,但同时不利于元素的插入和删除,如当在最前端插入元素,会导致所有其余所有元素后移一位,造成N次迭代,复杂度O(N)。实现其简单的增删改查,提供自动扩充功能,并内置迭代器,可以进行增广遍历。

功能描述

  • 提供易于使用的ArrayList泛型实现,避免与类库冲突,命名为MyArrayList,其包含的主要细节如下:
    • MyArrayList保持基础数组,数组的容量,以及存储在MyArrayList中当前的项数;
    • MyArrayList设计一种机制用来改变数组容量,通过获得一个新数组,将老数组的内容复制到新数组,允许JVM回收老数组;
    • MyArrayList提供set和get的实现;
    • MyArrayList提供基本的例程。如size(), clear(), isEmpty()等典型的单行程序;同时提供remove和两个版本的add,一个在任意位置添加,一个在集合末端添加,并且数组容量不足,add方法将扩充数组;
    • MyArrayList提供一个实现Iterator接口的类,该类存储迭代序列中的下一个下标,并提供next, hasNext, remove方法实现。MyArrayList的迭代器方法直接返回实现Iterator接口的该类的一个新的实例,代码中采用两种方式,私有内部类和嵌套类实现迭代器。

代码实现

package com.yam.base;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * ArrayList的实现
 * @author: Ympery
 * @date: 2017/3/8 11:10.
 */
public class MyArrayList<AnyType> implements Iterable<AnyType> {

    /**
     * 默认大小
     */
    private static final int DEFAULT_CAPACITY = 10;

    /**
     * 集合大小
     */
    private int theSize;

    /**
     * 类型数组
     */
    private AnyType[] theItems;

    public MyArrayList() { clear(); }

    /**
     * 清理集合
     */
    public void clear() {
        theSize = 0;
        ensureCapacity(DEFAULT_CAPACITY);
    }

    /**
     * 返回集合容量
     * @return 大小
     */
    public int size() { return theSize; }

    /**
     * 判断是否为空
     * @return
     */
    public boolean isEmpty() { return 0 == size(); }

    /**
     * 将集合缩减到内容大小
     */
    public void trimToSize() { ensureCapacity(size()); }

    /**
     * 获取集合元素
     * @param idx 位置
     * @return
     */
    public AnyType get(int idx) {
        if (0 > idx || idx >= size())
            throw new ArrayIndexOutOfBoundsException();
        return theItems[idx];
    }

    /**
     * 根据元素位置设置该元素值
     * @param idx 位置
     * @param newVal 要设置的值
     * @return 该元素原有的值
     */
    public AnyType set(int idx, AnyType newVal) {
        if (0 > idx || idx >= size())
            throw new ArrayIndexOutOfBoundsException();
        AnyType old = theItems[idx];
        theItems[idx] = newVal;
        return old;
    }

    /**
     * 列表copy,容量的扩张和收缩
     * @param newCapacity
     */
    public void ensureCapacity(int newCapacity) {
        if (newCapacity < theSize)
            return;

        AnyType[] old = theItems;
        // 因为泛型数组的创建时非法的,因此创建一个有界数组,强制转换
        theItems = (AnyType[]) new Object[newCapacity];

        for (int i = 0; i < size(); i++)
            theItems[i] = old[i];
    }

    /**
     * 在list的末端插入x
     * @param x
     * @return
     */
    public boolean add(AnyType x) {
        add(size(), x);
        return true;
    }

    /**
     * 向集合中插入元素(任意位置)
     * @param idx
     * @param x
     */
    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++;
    }

    /**
     * 删除指定位置元素
     * @param idx
     * @return
     */
    public AnyType remove(int idx) {
        AnyType removedItem = theItems[idx];
        for (int i = idx; i < size(); i++)
            theItems[i] = theItems[i++];
        theSize--;

        return removedItem;
    }


    /**
     * 获取一个当前集合的迭代器
     * @return
     */
    /*public Iterator<AnyType> iterator() {
        return new ArrayListIterator();
    }*/

    /**
     * 内部类构造集合迭代器
     */
    /*private class ArrayListIterator implements Iterator<AnyType>{

        *//**
         * 记录当前遍历位置
         *//*
        private int current = 0;

        */
    /**
     * 是否由下一个元素
     *
     * @return
     *//*
        @Override
        public boolean hasNext() {
            return current < theSize;
        }

        @Override
        public AnyType next() {
            if (!hasNext())
                throw new NoSuchElementException();
            return theItems[current++];
        }

        @Override
        public void remove() {
            MyArrayList.this.remove(--current);
        }
    }*/

    /**
     * 这里在获取迭代器必须传入该集合本身
     * @return
     */
    public ArrayListIterator<AnyType> iterator() {
        return new ArrayListIterator<>(this);
    }

    /**
     * 使用嵌套类构造集合迭代器
     * @param <AnyType>
     */
    private static class ArrayListIterator<AnyType> implements Iterator<AnyType> {

        /*
         * 当前位置
         */
        private int current = 0;
        private MyArrayList<AnyType> theList;

        public ArrayListIterator(MyArrayList list){
            theList = list;
        }

        @Override
        public boolean hasNext() {
            return current < theList.size();
        }

        @Override
        public AnyType next() {
            if (!hasNext())
                throw new NoSuchElementException();
            return theList.theItems[current++];
        }

        @Override
        public void remove() {
            theList.remove(--current);
        }
    }

    /**
     * 测试
     * @param args
     */
    public static void main(String[] args) {
        MyArrayList<Character> strList = new MyArrayList<>();
        char c = 'a';
        for (int i = 0; i < 15; i++)
            strList.add(c++);

        for(char ch : strList)
            System.out.print(ch + " ");

        System.out.println("删除之前:" + strList.size());

        strList.remove(5);

        for(char ch : strList)
            System.out.print(ch + " ");
        System.out.println("删除之后:" + strList.size());
    }
}

  注:代码中的注释部分是采用内部类迭代器实现,文章最后采用了嵌套类实现(我习惯吧静态内部类称作嵌套类),两者区别这里不做赘述。

相关文章:

  • LinkedList实现
  • Stack的实现
  • Queue的实现
  • 更改gitlab默认端口
  • JVM运行时数据区
  • Eclipse Memory Analysis的安装和使用
  • 基于Redis实现的延迟消息队列
  • elasticsearch插件x-pack安装和使用
  • 基于Rabbitmq实现延迟消息
  • 使用拦截器进行数据加解密
  • JVM垃圾收集和内存分配
  • React Jest单元测试配置
  • acme 证书管理
  • GitLab邮箱配置
  • int n=10的sizeof 为什么是四_int、float、double数据类型之间转换的原则
  • 【刷算法】从上往下打印二叉树
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • Consul Config 使用Git做版本控制的实现
  • Java Agent 学习笔记
  • JAVA_NIO系列——Channel和Buffer详解
  • java8 Stream Pipelines 浅析
  • nodejs调试方法
  • Python实现BT种子转化为磁力链接【实战】
  • Redash本地开发环境搭建
  • 百度小程序遇到的问题
  • 复杂数据处理
  • 工作中总结前端开发流程--vue项目
  • 基于webpack 的 vue 多页架构
  • 微信小程序开发问题汇总
  • 在weex里面使用chart图表
  • 从如何停掉 Promise 链说起
  • 直播平台建设千万不要忘记流媒体服务器的存在 ...
  • ​软考-高级-信息系统项目管理师教程 第四版【第14章-项目沟通管理-思维导图】​
  • # 手柄编程_北通阿修罗3动手评:一款兼具功能、操控性的电竞手柄
  • (16)Reactor的测试——响应式Spring的道法术器
  • (3)(3.5) 遥测无线电区域条例
  • (6)添加vue-cookie
  • (Git) gitignore基础使用
  • (二)c52学习之旅-简单了解单片机
  • (附源码)ssm基于jsp高校选课系统 毕业设计 291627
  • (三) prometheus + grafana + alertmanager 配置Redis监控
  • (五)关系数据库标准语言SQL
  • ./和../以及/和~之间的区别
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .NET Core 中的路径问题
  • .Net MVC4 上传大文件,并保存表单
  • .NET 事件模型教程(二)
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .net和php怎么连接,php和apache之间如何连接
  • .Net下C#针对Excel开发控件汇总(ClosedXML,EPPlus,NPOI)
  • /usr/bin/python: can't decompress data; zlib not available 的异常处理
  • @Transactional注解下,循环取序列的值,但得到的值都相同的问题
  • [2669]2-2 Time类的定义
  • [ABP实战开源项目]---ABP实时服务-通知系统.发布模式