Java 抽象容器类源码剖析

news2025/8/14 9:01:45

总体介绍

抽象容器类接口和具体容器类的关系如图所示,顶层包括Collection、List、Set、Queue、Deque和Map6个抽象容器类。

AbstractCollection:实现了Collection接口,被抽象类AbstractList、AbstractSet、AbstractQueue继承,ArrayDeque也继承自AbstractCollection。

AbstractList:父类是AbstractCollection,实现了List接口,被ArrayList、Abstract-SequentialList继承。

AbstractSequentialList:父类是AbstractList,被LinkedList继承。

AbstractMap:实现了Map接口,被TreeMap、HashMap、EnumMap继承。

AbstractSet:父类是AbstractCollection,实现了Set接口,被HashSet、 TreeSet和EnumSet继承。

AbstractQueue:父类是AbstractCollection,实现了Queue接口,被PriorityQueue继承。

本文分别介绍这些抽象类,包括它们提供的基础功能、如何实现、如何进行扩展等。

以AbstractCollection为例

AbstractCollection提供了Collection接口的基础实现,它实现了如下方法:

public boolean addAll(Collection<? extends E> c)
public boolean contains(Object o)
public boolean containsAll(Collection<?> c)
public boolean isEmpty()
public boolean remove(Object o)
public boolean removeAll(Collection<?> c)
public boolean retainAll(Collection<?> c)
public void clear()
public Object[] toArray()
public <T> T[] toArray(T[] a)
public String toString()

由于AbstractCollection不知道数据是怎么存储的,它依赖于如下更为基础的方法:

public boolean add(E e)
public abstract int size();
public abstract Iterator<E> iterator();

add方法的默认实现是:

public boolean add(E e) {
       throw new UnsupportedOperationException();
}

代码抛出“操作不支持”异常,如果子类集合是不可被修改的,这个默认实现就可以了,否则,必须重写add方法。addAll方法的实现就是循环调用add方法。
size方法是抽象方法,子类必须重写。isEmpty方法就是检查size方法的返回值是否为0。toArray方法依赖size方法的返回值分配数组大小。
iterator方法也是抽象方法,它返回一个实现了迭代器接口的对象,子类必须重写。迭代器
定义了三个方法:

boolean hasNext();
E next();
void remove();

如果子类集合是不可被修改的,选代器不用实现remove方法,否则,三个方法都必须实现。

除了接口中的方法,Collection接口文档建议,每个Collection接口的实现类都应该提供至少两个标准的构造方法,一个是默认构造方法,另一个接受一个Collection类型的参数。

具体如何通过继承AbstractCollection来实现自定义容器呢?下面通过一个简单的例子来说明。我们使用自己实现的动态数组容器类DynamicArray来实现一个简单的Collection。

public class DynamicArray<E> {
       //...
       public E remove(int index) {
           E oldValue = get(index);
           int numMoved = size - index - 1;
           if(numMoved > 0)
               System.arraycopy(elementData, index + 1, elementData, index,
                       numMoved);
           elementData[--size] = null;
           return oldValue;
       }
       public void add(int index, E element) {
           ensureCapacity(size + 1);
           System.arraycopy(elementData, index, elementData, index + 1,
                            size - index);
           elementData[index] = element;
           size++;
       }
}

基于DynamicArray,再实现一个简单的迭代器类DynamicArrayIterator

public class DynamicArrayIterator<E>  implements Iterator<E>{
       DynamicArray<E> darr;
       int cursor;
       int lastRet = -1;
       public DynamicArrayIterator(DynamicArray<E> darr){
           this.darr = darr;
        }
    @Override
    public boolean hasNext() {
     return cursor != darr.size();
    }
    @Override
    public E next() {
        int i = cursor;
        if(i >= darr.size())
            throw new NoSuchElementException();
        cursor = i + 1;
    lastRet = i;
        return darr.get(i);
    }
    @Override
    public void remove() {
    if(lastRet < 0)
        throw new IllegalStateException();
    darr.remove(lastRet);
    cursor = lastRet;
    lastRet = -1;
}

基于DynamicArray和DynamicArrayIterator,通过继承AbstractCollection,我们来实现一个简单的容器类MyCollection。MyCollection提供了两个构造方法,并重写了size、add和iterator方法,这些方法内部使用了DynamicArray和DynamicArrayIterator。

public class MyCollection<E> extends AbstractCollection<E> {
       DynamicArray<E> darr;
       public MyCollection(){
           darr = new DynamicArray<>();
       }
       public MyCollection(Collection<? extends E> c){
           this();
addAll(c); }
       @Override
       public Iterator<E> iterator() {
           return new DynamicArrayIterator<>(darr);
       }
       @Override
       public int size() {
           return darr.size();
       }
       @Override
       public boolean add(E e) {
           darr.add(e);
           return true;
       }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1453679.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

飞天使-k8s知识点19-kubernetes实操4-资源调度 标签和选择器:Label与Selector的使用-版本回退

文章目录 添加label资源调度 Deployment&#xff1a;创建与配置文件解析rs pod deploy 的关联信息展示Deployment&#xff1a;滚动更新Deployment&#xff1a;回滚回退版本实际操作 添加label [rootkubeadm-master1 test]# kubectl get pod NAME …

OpenCV Mat实例详解 四

OpenCV Mat实例详解三中详细介绍来了OpenCV Mat类的公有静态成员函数&#xff0c;下面介绍OpenCV Mat类的其他常用成员函数。 OpenCV Mat类常用成员函数 Mat & adjustROI (int dtop, int dbottom, int dleft, int dright)&#xff1b; dtop ROI 上边界移动值&#xff0c;如…

Java实现新能源电池回收系统 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 用户档案模块2.2 电池品类模块2.3 回收机构模块2.4 电池订单模块2.5 客服咨询模块 三、系统设计3.1 用例设计3.2 业务流程设计3.3 E-R 图设计 四、系统展示五、核心代码5.1 增改电池类型5.2 查询电池品类5.3 查询电池回…

LabVIEW智能监测系统

LabVIEW智能监测系统 设计与实现一个基于LabVIEW的智能监测系统&#xff0c;通过高效的数据采集和处理能力&#xff0c;提高监测精度和响应速度。系统通过集成传感器技术与虚拟仪器软件&#xff0c;实现对环境参数的实时监测与分析&#xff0c;进而优化监控过程&#xff0c;提…

一些配置问题记录

真的很感慨 为什么一开始的下载的软件还能用 卸载或重装后的软件总是存在各种各样的错误 真令人心烦 GNURADIO运行简单的采集信号程序报错&#xff0c; 其实不太理解为什么会出现这类错误&#xff0c;解决方法为 安装 jackd2 软件包&#xff0c;然后尝试手动启动 Jack 服务器…

通过玩游戏学会AWS

游戏名字&#xff1a; Cloud Quest 类型&#xff1a;亚马逊云科技官方出了一款 3D 角色扮演、虚拟城市建造形式的游戏实验课 进入方法&#xff1a;浏览器搜索 Cloud Quest&#xff08;或扫描下方二维码&#xff09;进入 Cloud Quest 课程页。 选择以下的链接 点击进行注册 进…

力扣题目训练(12)

2024年2月5日力扣题目训练 2024年2月5日力扣题目训练476. 数字的补数482. 密钥格式化485. 最大连续 1 的个数148. 排序链表164. 最大间距 2024年2月5日力扣题目训练 2024年2月5日第十二天编程训练&#xff0c;今天主要是进行一些题训练&#xff0c;包括简单题3道、中等题2道和…

21种matlab信号分解方法汇总

21中信号分解方法汇总 CEEMD(互补集合经验模态分解)CEEMDAN(自适应噪声完备集合经验模态分解) EEMD(集合经验模态分解&#xff09;EMD(经验模态分解)ESMD(极点对称模态分解&#xff09;EWT(经验小波变换分解)FEEMD(快速EEMD分解)ICEEMDAN(改进自适应噪声完备集合经验模态分解)L…

微波炉维修笔记

微波主要是靠2.45GHz 左右的微波(12.2cm 波长)加热水分子实现食物加热 所有不要使用金属器皿进行加热&#xff0c;要么因为电磁屏蔽&#xff0c;起不到加热效果&#xff0c;要么火光四射 微波炉基本组成 借鉴姜师傅的视频 碰到不加热其它都正常的问题 1.检查高压电容 使用万…

安装luajit及使用python运行lua脚本

使用Python运行lua脚本前&#xff0c;需要先安装LuaJIT&#xff0c;LuaJIT的官网是下载 (luajit.org) 目前已不再使用.exe文件的下载方式&#xff0c;需要使用Git从公共仓库下载源码&#xff0c;git命令为&#xff1a; $ git clone https://luajit.org/git/luajit.git 下载后…

解决ubuntu登录密码问题

解决ubuntu登录密码问题 不要随便删除密码&#xff0c;不要随便改密码&#xff0c;很容导致密码过期&#xff0c;或者密码无效。参考了很多人的做法&#xff0c;都没有得到解决。下面的过程&#xff0c;够详细了&#xff0c;我就是这么搞好的。 1、重启虚拟机&#xff0c;不停…

数据的力量:构筑现代大型网站之数据库基础与应用

目录 数据库基础知识--前言 大型网站架构特点 DBA数据库管理员 什么是数据? 数据存储 什么是数据库 数据表的概念 为什么需要mysql这样的数据库管理工具&#xff1f;★ DBMS 收费数据库与免费数据库 运维和数据库 开发与运维的不同阶段 数据库类别 数据库具体应用…

数据结构第十六天(二叉树层序遍历/广度优先搜索(BFS)/队列使用)

目录 前言 概述 接口 源码 测试函数 运行结果 往期精彩内容 前言 从前的日色变得慢&#xff0c;车&#xff0c;马&#xff0c;邮件都慢&#xff0c;一生,只够爱一个人。 概述 二叉树的层序遍历可以使用广度优先搜索&#xff08;BFS&#xff09;来实现。具体步骤如下&…

Open CASCADE学习|布尔运算后消除内部拓扑

在CAD建模中&#xff0c;布尔运算是一种逻辑运算方法&#xff0c;通过这种方法&#xff0c;可以创建、修改或组合几何对象。布尔运算主要包括并集&#xff08;UNION&#xff09;、交集&#xff08;INTERSECT&#xff09;和差集&#xff08;SUBTRACT&#xff09;三种运算。 并集…

React18原理: React核心对象之ReactElement对象和Fiber对象

React中的核心对象 在React应用中&#xff0c;有很多特定的对象或数据结构.了解这些内部的设计&#xff0c;可以更容易理解react运行原理列举从react启动到渲染过程出现频率较高&#xff0c;影响范围较大的对象&#xff0c;它们贯穿整个react运行时 如 ReactElement 对象如 Fi…

「函数小课堂」~(C语言)

先赞后看&#xff0c;不足指正! 这将对我有很大的帮助&#xff01; 所属专栏&#xff1a;C语言知识 阿哇旭的主页&#xff1a;Awas-Home page 目录 引言 1. 函数的概念 2. 函数的类型 2.1 库函数 2.2 自定义函数 2.2.1 语法 2.2.2 举例 3. 函数的参数 3.1 实参 3.2 形参…

International Marine Purchasing Association 7(IMPA7)

​IMPA7物料 物料手持下载链接&#xff1a;https://pan.baidu.com/s/13m0EELpEZWlL55UhsRvI5g?pwd8888 提取码&#xff1a;8888 国际船舶物料准则International Marine Purchasing Association 7(IMPA7)。 IMPA是英文“International Marine Purchasing Association”缩写…

vue-vuex(七)

阅读文章你可以收获&#xff1a; 1 了解什么是vuex 2 知道如何在vue项目中集成vuex 3 知道vuex由什么组成&#xff0c;并如何使用 vuex概述 1. 是什么&#xff1a;vuex 是一个 vue 的 状态管理工具&#xff0c;状态就是数据。 大白话&#xff1a;vuex 是一个插件&#xff0…

Swing程序设计(10)列表框,文本框,文本域,密码框

文章目录 前言一、列表框二、文本框&#xff08;域&#xff09; 1.文本框2.文本域三、密码框总结 前言 该篇文章简单介绍了Java中Swing组件里的列表框、文本框、密码框。 一、列表框 列表框&#xff08;JList&#xff09;相比下拉框&#xff0c;自身只是在窗体上占据固定的大小…

CSS概述 | CSS的引入方式 | 选择器

文章目录 1.CSS概述2.CSS的引入方式2.1.内部样式表2.2.行内样式表2.3.外部样式表 3.选择器 1.CSS概述 CSS&#xff0c;全称Cascading Style Sheets&#xff08;层叠样式表&#xff09;&#xff0c;是一种用来设置HTML&#xff08;或XML等&#xff09;文档样式的语言。CSS的主要…