探索Java集合框架—数据结构、ArrayList集合

一、背景介绍

Java集合的使用相信大家都已经非常得心应手,但是我们怎么做到知其然,更知其所以然这种出神入化的境界呢?我们揭开集合框架底层神秘面纱来一探究竟

目录

一、背景介绍

二、思路&方案

数据结构是什么?

数据结构可以分为线性和非线性两种数据结构

线性数据结构:

非线性数据结构:

Java集合分类

Collection接口:

Map接口:

三、过程

ArrayList和LinkedList的区别有哪些?

ArrayList是如何存储数据的?

ArrayList扩容机制

①、如何进行扩容的?

②、增加元素

③、ArrayList给指定位置插入元素

④、删除元素

按照下标位置删除元素

按照内容删除元素

四、总结


二、思路&方案

在说集合之前我们要先了解数据结构这一概念

数据结构是什么?

数据结构时对数据进行组织和存储一种方式,数据使用不同的数据结构组织和存储时所带来的时间和空间性能也是不同的。List、Set、Map集合背后使用了不同的数据结构,我们理解为集合是一种数据结构的具体实现。例如:可以使用数组结构来实现集合,当访问数组元素的时候通过数组下标查找时更快。

程序=数据结构+算法。数据结构还提供了一些各种查找、排序算法,集合可以用来解决一堆数据的处理问题,如:查找、排序、去重等等

数据结构可以分为线性和非线性两种数据结构

线性数据结构:

特点:

一对一的关系并且逻辑上有序,数据元素之间存在一个前后关系,每个元素只有一个直接前驱和一个直接后去

组成:

  • 数组(Array):相同类型元素并且连续存储
  • 链表(LinkedList):一系列node节点,每个节点包括数据、指向下一个节点的指针
  • 栈(Stack):先进后出(LIFO),在栈顶进行删除和插入操作
  • 队列(Queue):先进先出(FIFO),在队尾插入、对头删除元素

非线性数据结构:

特点:

多对多关系,数据元素之间不存在直接的前后关系,元素和元素之间通过指针相连,

包括:

  • 树(Tree):一组node节点组成,每个父节点下级可以有子节点,节点之间是上下层次关系
  • 图(Graph):一组节点、边之间的关系
  • 堆(Heap):实现优先队列
  • 散列表(Hash Table):根据关键字可以直接查询数据,通过散列函数确认存储位置

结合上面讲到的数据结构,我们来看下Java究竟是如何应用的


Java集合分类

集合相关类和接口都在java.util中,从宏观上我们把Java集合分为了以Collection为中心的实现类、以Map为中心的实现类, Collection和Map两个接口下面分别有不同的实现类,它们都是用来存储和操作数据的集合

Collection接口:

特点:

一组对象的集合,通过索引或迭代器访问元素,元素可以重复

包括:

  • List:有序集合
  • Set:无序集合
  • Queue:先进先出集合

Map接口:

特点:

键值对映射的集合,通过key查找value,每个key是唯一的

包括:

  • HashMap:通过哈希表实现,无序
  • TreeMap:基于红黑树实现,有序
  • LinkedHashMap:哈希表+双向链表实现,顺序插入

今天先重点来讲讲List集合中ArrayList增删改查是如何实现的



三、过程

ArrayList和LinkedList的区别有哪些?

ArrayList是如何存储数据的?

底层是数组,数组存储的数据的特点是元素类型相同并且数组容量固定

数组存储容量固定?那在实际业务场景中数据肯定是不固定的呀?如何解决?

ArrayList扩容机制

ArrayList提供了自动扩容机制,当插入数据时候底层会先判断是否需要扩容,如果当前容量+1超过数组长度,就会进行扩容,反之。

①、如何进行扩容的?

ArrayList内部封装了一个动态再分配的对象数组,ArrayList的底层数据库初始容量为10,扩容因子为1.5

 

②、增加元素

当我们第一次添加元素使用add()方法添加元素的过程中,底层的流程是这样的:

内部会调用ensureExplicitCapacity()方法判断添加元素之后的数组长度是否大于数组容量,如果超出数组容量调用grow()方法扩容,否则给数组长度+1

当第一次对数组进行add添加元素的时候,才会把内部的数组扩容为10,这也是数组的第一次扩容

 注意:

  • 数组长度是指当前数组内元素的个数
  • 数组容量是指数组所能容纳的长度

示意图:

那如果要添加的元素不足数组容量呢?现在我们来看下具体是如何扩容的?

假设场景:数组中已经有10个元素,需要添加第11个元素

calculateCapacity方法内部首先会判断elementData数组是否是默认的空数组(看是否往数组里面添加了元素),如果不是默认数组则返回添加元素之后数组所需要的长度

如果添加元素之后的数组长度超出了数组容量,则说明需要扩容,调用grow()方法进行扩容

 grow()方法内部会调用一个交copyOf方法进行扩容,会创建一个1.5倍的新数组,将原来的数组元素挪到新数组中

此时ArrayList扩容为原来的大小+原来大小/2=10+5=15,数组扩容后容量为15

 扩容后的数组示意图如下:

add(E e)添加元素的流程为:

第一步、判断是否需要扩容:

        需要扩容

                ①、计算新数组容量:newCapacity = oldCapacity + (oldCapacity >> 1)

                ②、创建新数组:elementData = Arrays.copyOf(elementData, newCapacity)

第二步、追加元素到数组末尾 。  elementData[size++] =element;

第三步、添加成功

③、ArrayList给指定位置插入元素

示例:

添加指定位置流程如下:

第一步、检查下标是否越界

        越界:抛出IndexOutOfBoundsException异常

第二步、判断是否需要扩容,如果需要扩容则扩容

第三步、后移元素.从指定要插入元素位置依次向后移动一个位置,此时指定要插入的位置为空

第四步、插入新元素。将要插入的元素放入指定位置

第五步、更新数组大小。size+1

        

注意: 其中rangeCheckForAdd(index)方法会检查下标是否越界,如果要插入的元素位置超出了当前数组的容量,会抛出”IndexOutOfBoundsException“的异常

 示意图:

④、删除元素

按照下标位置删除元素

按照内容删除元素


四、总结

通过分析源码我们了解了ArrayList底层增删改查操作具体的细节,再次总结

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

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

相关文章

HTML基础--标签

目录 列表标签 有序列表 type属性 有序列表嵌套 无序列表 type属性 无序列表嵌套 常见应用场景 表格标签 表格展示效果 表格属性 表格单元格合并 单元格合并属性 列表标签 HTL作为构建网页内容的标记语言,提供了多种列表标签,用于在网页中展…

mysql通过.frm和.ibd 文件恢复数据库

问题背景:由于强制在服务关闭mysql导致部分数据表以及数据丢失 如下图只有.frm .ibd的文件为我的问题文件 查找不到表结构和表数据目录D:XXXX\mysql-5.7.24-winx64\data\mydata 从frm文件中恢复表结构 先把原来的数据备份一次 避免过程中出错 先备份之前数据的.fr…

工作中提高CSS的编写效率,可以多用这三个CSS伪类

:where 基本使用 :where() CSS 伪类函数接受选择器列表作为它的参数&#xff0c;将会选择所有能被该选择器列表中任何一条规则选中的元素。 以下代码&#xff0c;文本都会变成 yellow 颜色 :where(div p) span {color: yellow; }<div class"test-div"><…

书单制作方法详细步骤分享,想学的小伙伴看过来

如果你是一个热爱阅读的人&#xff0c;那么制作一份书单可能是一件有趣和有用的事情。在这篇文章中&#xff0c;我们将分享一些书单制作的方法和注意事项。 选择主题和书籍 首先&#xff0c;你需要选择一种主题&#xff0c;以便你可以按照主题来选择书籍。选择一个你感兴趣的主…

《人工智能算法图解》书籍分享(包邮送书)

文章目录 人工智能介绍书籍分享抽奖包邮送书 人工智能介绍 人工智能算法是一种能够模拟人类智能行为的计算机算法。它通过分析和处理大量的数据&#xff0c;利用机器学习、深度学习和自然语言处理等技术&#xff0c;实现自主学习、推理和决策的能力。 人工智能算法的发展经历…

Qt5升级到Qt6分步迁移教程

Qt框架的一个新的长期支持版本6.5最近发布。它为以前的版本引入了许多修复、改进和新功能。有些可能对您的应用程序有用&#xff08;如果不是现在&#xff0c;可能会在将来&#xff09;&#xff0c;因此最好将应用程序迁移到最新版本的框架。 仍然有许多应用程序仍在使用Qt 5&…

白鲸开源 DataOps 平台加速数据分析和大模型构建

作者 | 李晨 编辑 | Debra Chen 数据准备对于推动有效的自助式分析和数据科学实践至关重要。如今&#xff0c;企业大都知道基于数据的决策是成功数字化转型的关键&#xff0c;但要做出有效的决策&#xff0c;只有可信的数据才能提供帮助&#xff0c;随着数据量和数据源的多样…

TCP协议基础

一&#xff1a; TCP协议是什么&#xff1f; TCP协议是基于面向连接&#xff0c;可靠传输&#xff0c;基于字节流的传输层通信协议 1. 面向连接 TCP协议是一种面向连接的协议&#xff0c;意味着在双方在建立数据传输之前&#xff0c;需要进行一个逻辑上的连接&#xff0c;且是…

【数据结构】队列篇| 超清晰图解和详解:循环队列模拟、用栈实现队列、用队列实现栈

博主简介&#xff1a;努力学习的22级计算机科学与技术本科生一枚&#x1f338;博主主页&#xff1a; 是瑶瑶子啦每日一言&#x1f33c;: 每一个不曾起舞的日子&#xff0c;都是对生命的辜负。——尼采 目录 一、 模拟实现循环队列二、用栈实现队列⭐三、225. 用队列实现栈 一、…

【日积月累】后端刷题日志

刷题日志 说说对Java的理解JAVA中抽象类和接口之间的区别Java中的泛型 和equals()的区别八种基本数据类型与他们的包装类在一个静态方法内调用一个非静态成员为什么是非法的静态方法与实例方法有何不同重载与重写深拷贝浅拷贝面向过程与面向对象成员变量与局部变量Spring框架Sp…

无涯教程-Flutter - 简介

Flutter是一个由谷歌开发的开源移动应用软件开发工具包&#xff0c;用于为Android、iOS、 Windows、Mac、Linux、Google Fuchsia开发应用。 通常&#xff0c;创建移动应用程序是一个非常复杂和具有挑战性的任务。有许多框架可用&#xff0c;它提供了开发移动应用程序的出色函数…

openssh---Windows下git安装配置gitlab

安装openssh 1. 专业版Win10/11默认自带&#xff0c;可以查看是否开启 1. Get-WindowsCapability -Online | Where-Object Name -like OpenSSH* 2. Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 3. Add-WindowsCapability -Online -Name OpenSSH.Serve…