探索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.mzph.cn/news/53521.shtml

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

相关文章

Aspose.Tasks for .NET V23Crack

Aspose.Tasks for .NET V23Crack 改进了大型项目的内存占用。 添加了API,允许您在应用程序无法访问系统字体文件夹时指定用户的字体文件夹。 Aspose.Tasksfor.NET是处理MicrosoftProject文件的可靠的项目管理API。API支持在不依赖Microsoft Project的情况下读取、写…

【C++】list

list 1. 简单了解list2. list的常见接口3. 简单实现list4. vector和list比较 1. 简单了解list list的底层是带头双向循环列表。因此list支持任意位置的插入和删除,且效率较高。但其缺陷也很明显,由于各节点在物理空间是不连续的,所以不支持对…

ElasticSearch简介、安装、使用

一、什么是ElasticSearch? Elasticsearch 是 Elastic Stack 核心的分布式搜索和分析引擎。 Logstash 和 Beats 有助于收集、聚合和丰富您的数据并将其存储在 Elasticsearch 中。 Kibana 使您能够以交互方式探索、可视化和分享对数据的见解,并管理和监…

如何搭建智能家居系统并通过内网穿透实现远程控制家中设备

文章目录 前言1. 安装Home Assistant2. 配置Home Assistant3. 安装cpolar内网穿透3.1 windows系统3.2 Linux系统3.3 macOS系统 4. 映射Home Assistant端口5. 公网访问Home Assistant6. 固定公网地址6.1 保留一个固定二级子域名6.2 配置固定二级子域名 前言 Home Assistant&…

stm32基于HAL库驱动外部SPI flash制作虚拟U盘

stm32基于HAL库驱动外部SPI flash制作虚拟U盘 📌参考文章:https://xiaozhuanlan.com/topic/6058234791🎞实现效果演示: 🔖上图中的读到的FLASH_ID所指的是针对不同容量,所对应的ID。 //W25X/Q不同容量对应…

【面试】线上 CPU 100% 问题排查

回答套路一般为&#xff1a;线上服务器没有排查过&#xff0c;线上服务器只有运维才有操作权限。在平时开发的时候&#xff0c;在测试服务器上排查过。 一、复现代码 public class Test {public static void main( String[] args ){int a 0;while (a < 100) {a * 10;}} }…

Redis知识点总结

概述 Redis诞生于2009年&#xff0c;全称是Remote Dictionarty Server(远程词典服务器) 只支持单线程 非关联&#xff1a;主要指的是表中没有主外键等概念 Redis是一款内存数据库&#xff0c;主要存储键值对类型的数据 基本用法 注意&#xff1a;该操作是在cli中进行的 首…

windows安装多个版本node

1.下载nvm-setup版本 安装过程会检测到你当前使用的node版本 提示 Node v12.14.0 is already installed. Do you want NVM to control this version? 翻译&#xff1a;已安装节点v12.14.0。你想让NVM控制这个版本吗? 选择 是(Y)。 nvm默认为我们增添了环境变量&#xff0c;…

docker 安装 Wordpress 用lnmp搭建出现的故障

第一个故障就是mysql出现的故障了 你起mysql镜像是这么起的导致pid号用不了 docker run --namemysql -d --privileged --device-write-bps /dev/sda:10M -v /usr/local/mysql --net mynetwork --ip 172.20.0.20 mysql:lnmp 解决方法 docker run --namemysql -d --privilege…

【MySQL系列】统计函数(count,sum,avg)详解

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …

Java中HashMap的基本介绍和详细讲解,HashMap的遍历以及HashMap的底层源码的分析

HashMap 基本介绍 HashMap 是 Java 中的一个集合类&#xff0c;实现了 Map 接口&#xff0c;用于存储键值对&#xff08;key-value&#xff09;数据。它基于哈希表的数据结构实现&#xff0c;可以实现高效的查找、插入和删除操作。 HashMap 细节讨论 无序性&#xff1a; Has…

[Linux]命令行参数和进程优先级

[Linux]命令行参数和进程优先级 文章目录 [Linux]命令行参数和进程优先级命令行参数命令行参数的概念命令函参数的接收编写代码验证 进程优先级进程优先级的概念PRI and NI使用top指令修改nice值 命令行参数 命令行参数的概念 命令行参数是指用于运行程序时在命令行输入的参数…

Qt6和Rust结合构建桌面应用

桌面应用程序是原生的、快速的、安全的&#xff0c;并提供Web应用程序无法比拟的体验。 Rust 是一种低级静态类型多范式编程语言&#xff0c;专注于安全性和性能&#xff0c;解决了 C/C 长期以来一直在努力解决的问题&#xff0c;例如内存错误和构建并发程序。 在桌面应用程序开…

ToolAI–全球最完整最全面的AI人工智能工具集合

ToolAI是一个全球最完整最全面的AI人工智能工具集合网站&#xff0c;收集了全球最完整的数千个AI网站、工具、app&#xff0c;包含文案写作、邮件助手、聊天机器人、社交媒体等等各种行业类型的AI工具&#xff0c;可以按照地区或者分类进行查找浏览&#xff0c;目前收集6800 人…

垃圾回收器

垃圾回收器就是垃圾回收的实践者&#xff0c;随着JDK的发展&#xff0c;垃圾回收器也在不断的更迭&#xff0c;在不同的场合下使用不同的垃圾回收器&#xff0c;这也是JVM调优的一部分。 1.垃圾回收器的分类 按线程可分为单线程(串行)垃圾回收器和多线程(并行)垃圾回收器。 按…

Java之ApI之Math类详解

1 Math类 1.1 概述 tips&#xff1a;了解内容 查看API文档&#xff0c;我们可以看到API文档中关于Math类的定义如下&#xff1a; Math类所在包为java.lang包&#xff0c;因此在使用的时候不需要进行导包。并且Math类被final修饰了&#xff0c;因此该类是不能被继承的。 Math类…

Unity 之 GameObject.Find()在场景中查找指定名称的游戏对象

文章目录 GameObject.Find 是 Unity 中的一个函数&#xff0c;用于在场景中查找指定名称的游戏对象。这个函数的主要作用是根据游戏对象的名称来查找并返回一个引用&#xff0c;使您能够在代码中操作该对象。以下是有关 GameObject.Find 的详细介绍&#xff1a; 函数签名&…

某网站DES加密逆向分析实战

文章目录 一、抓包分析二、加密分析一、重写加密 一、抓包分析 分析站点&#xff1a; aHR0cDovL2VpcC5jaGFuZmluZS5jb20v 首先我们提交一下登陆信息&#xff1a; 搜索j_password查看加密函数: 把上图搜索到的encryptPassword函数拿出来分析一下&#xff1a; function encryptP…

智慧能源管理系统助力某制造企业提高能源利用效率

随着全球能源需求不断增加和能源价格的上涨&#xff0c;企业和机构日益意识到能源管理的重要性。传统的能源管理方式不仅效率低下&#xff0c;还容易造成资源浪费和环境污染。因此&#xff0c;许多企业开始探索采用智慧能源管理系统来提高能源利用效率&#xff0c;降低能源成本…

【面向大一新生IT技术社群招新啦,不来瞅瞅?】

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生 &#x1f43b;‍❄️个人主页&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;落798. &#x1f54a;️系列专栏&#xff1a;【零基础学java】 ----- 【重识c语言】 ---- 【计算机网络】—【Spri…