Java 抽象容器类源码剖析

总体介绍

抽象容器类接口和具体容器类的关系如图所示,顶层包括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;}@Overridepublic boolean hasNext() {return cursor != darr.size();}@Overridepublic E next() {int i = cursor;if(i >= darr.size())throw new NoSuchElementException();cursor = i + 1;lastRet = i;return darr.get(i);}@Overridepublic 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); }@Overridepublic Iterator<E> iterator() {return new DynamicArrayIterator<>(darr);}@Overridepublic int size() {return darr.size();}@Overridepublic boolean add(E e) {darr.add(e);return true;}
}

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LCR 127. 跳跃训练【简单】

LCR 127. 跳跃训练 题目描述&#xff1a; 今天的有氧运动训练内容是在一个长条形的平台上跳跃。平台有 num 个小格子&#xff0c;每次可以选择跳 一个格子 或者 两个格子。请返回在训练过程中&#xff0c;学员们共有多少种不同的跳跃方式。 结果可能过大&#xff0c;因此结果…

模仿 STM32 驱动开发格式实验

1.模仿 STM32 寄存器定义 为了开发方便&#xff0c; ST 官方为 STM32F103 编写了一个叫做 stm32f10x.h 的文件&#xff0c;在这个文件 里面定义了 STM32F103 所有外设寄存器&#xff0c;我们可以使用其定义的寄存器来进行开发&#xff0c;比如我 们可以用如下代码来初始…

HAL/LL/STD STM32 U8g2库 +I2C SSD1306/sh1106 WouoUI磁贴案例

HAL/LL/STD STM32 U8g2库 I2C SSD1306/sh1106 WouoUI磁贴案例 &#x1f4cd;基于STM32F103C8T6 LL库驱动版本&#xff1a;https://gitee.com/chcsx/platform-test/tree/master/MDK-ARM&#x1f3ac;视频演示&#xff1a; WouoUI移植磁贴案例&#xff0c;新增确认弹窗 &#x1f…

CVE-2022-24652 漏洞复现

CVE-2022-24652 开题 后台管理是thinkphp的&#xff0c;但是工具没检测出漏洞。 登陆后界面如下&#xff0c;上传头像功能值得引起注意 这其实就是CVE-2022-24652&#xff0c;危险类型文件的不加限制上传&#xff0c;是文件上传漏洞。漏洞路由/user/upload/upload 参考文章&a…

C#学习(十三)——多线程与异步

一、什么是线程 程序执行的最小单元 一次页面的渲染、一次点击事件的触发、一次数据库的访问、一次登录操作都可以看作是一个一个的进程 在一个进程中同时启用多个线程并行操作&#xff0c;就叫做多线程 由CPU来自动处理 线程有运行、阻塞、就绪三态 代码示例&#xff1a; cl…

【漏洞复现】蓝网科技临床浏览系统信息泄露漏洞

Nx01 产品简介 蓝网科技临床浏览系统是一个专门用于医疗行业的软件系统&#xff0c;主要用于医生、护士和其他医疗专业人员在临床工作中进行信息浏览、查询和管理。 Nx02 漏洞描述 蓝网科技临床浏览系统存在信息泄露漏洞&#xff0c;攻击者可以利用该漏洞获取敏感信息。 Nx03…

【二十八】springboot整合logback实现日志管理

本章节是记录logback在springboot项目中的简单使用&#xff0c;本文将会演示如何通过logback将日志记录到日志文件或输出到控制台等管理操作。将会从以下几个方面进行讲解。最后实现将特定级别的特定日志保存到日志文件。 一、依赖 <dependency><groupId>ch.qos.l…

OpenAI全新发布的Sora,到底意味着什么?

16日凌晨&#xff0c;OpenAI发布了文本视频的工具&#xff08;text-do-video&#xff09;Sora&#xff0c;整个世界再次被震撼。 Sora的出现&#xff0c;到底意味着什么&#xff1f; 目录 Sora的背景与概述Sora是什么&#xff1f;能为我们做些什么&#xff1f;存在的一些问题 文…

uni-app使用uView打开弹出层后输入框聚焦时placeholder错位问题

这里就不放效果了&#xff0c;大概意思就是在使用uView的popus时&#xff0c;在底部弹出后&#xff0c;如果弹窗中的输入框会造成一瞬间的placeholder文字错位&#xff0c;这个问题的主要是因为uView安全区适配导致 uView相关文档 https://www.uviewui.com/components/safeAr…

UE5中的DataTable说明

创建DataTable 在编辑器中创建 在文件夹空白处右击&#xff0c;选择Miscellaneous/DataTable&#xff0c;如图&#xff1a; 使用代码创建 // 创建DataTable实例 UDataTable* MyDataTable NewObject(); // 创建一个行结构体 UStruct* RowStruct UStruct::CreateEmpty(); // 添…

SPSSAU【文本分析】|社会关系网络图

社会网络关系图 社会网络关系图展示关键词之间的关系情况&#xff0c;此处的关系是指‘共词矩阵’&#xff0c;即两个关键词同时出现的频数情况&#xff0c;将‘共词矩阵’信息使用可视化方式进行呈现出来&#xff0c;接下来将分别阐述‘共词矩阵’和‘社会网络关系图’。 共词…

Java并发基础:ConcurrentSkipListMap全面解析

内容概要 ConcurrentSkipListMap类它融合了跳表的高效查找与并发控制的稳定性&#xff0c;在多线程环境下&#xff0c;该类提供了出色的线程安全性能&#xff0c;确保数据的一致性与完整性&#xff0c;其操作具有对数级别的时间复杂度&#xff0c;即使在大数据集下也能维持高效…