Java集合——Collection

news2024/11/24 4:34:33

Collection集合

Collection接口下主要有三大子接口 List Queue Set
在这里插入图片描述

1. List

List是有序可重复集合,根据索引下标来访问元素

List接口常见的三个实现类:ArrayListLinkedListVector

特点:

  • 集合中的元素允许重复
  • 集合中的元素有序,按照添加的顺序
  • 集合中的元素通过索引下标快速访问

1.1 ArrayList

List集合的主要实现类,底层使用动态数组 Object[] 存储,线程不安全。如果在创建时没有指定大小,会创建一个空数组,在第一次进行添加元素时,数组容量扩充为10(默认)

动态扩容

在调用add()方法添加元素时,会先将集合中的元素个数+1得到待添加元素的下标modCount,然后比较待添加元素的下标与数组长度,如果等于数组长度说明数组容量不足(数组下标从0开始),执行扩容grow(),扩容后得到一个新数组,将待添加的元素添加新数组末尾,并更新元素个数

private void add(E e, Object[] elementData, int s) {
    if (s == elementData.length)
        // 扩容
        elementData = grow();
    elementData[s] = e;
    size = s + 1;
}

public boolean add(E e) {
    modCount++;
    add(e, elementData, size);
    return true;
}

在进行扩容前先求出新增一个元素后最小所需容量(比如原本有10个元素新添加1个元素,最小所需容量就是11),然后再判断数组是否非空

  • 如果是空数组(还未创建)就新建一个大小为max(DEFAULT_CAPACITY, minCapacity) 的数组。
  • 非空数组,开始扩容先求扩容后数组容量,三个参数分别为 旧容量oldCapacity, 最小需要增加的容量
    minCapacity - oldCapacity, 旧容量的一半左右 oldCapacity >> 1 Math.max(minGrowth, prefGrowth) + oldLength 最小需要增加的容量和旧容量的一半左右两者取最大值 + 旧容量,求得扩容后数组容量newLength,随后与Integer.MAX_VALUE - 8 进行比较,如果没有超过就返回newLength。如果超过说明扩容后数组长度很大,此时需要调用hugeLength() 方法,判断 oldLength + minGrowth 的大小 如果超过Integer.MAX_VALUE 就报OutOfMemoryError 异常 ,没有超过Integer.MAX_VALUE - 8 就返回Integer.MAX_VALUE - 8 ,如果在Integer.MAX_VALUE - 8Integer.MAX_VALUE 之间就会返回Integer.MAX_VALUE

得到扩容后数组容量后就调用copyOf() 方法进行数组拷贝,底层是调用native本地方法进行拷贝

  private Object[] grow() {
      //求最小所需容量
        return grow(size + 1);
    }


private Object[] grow(int minCapacity) {
    int oldCapacity = elementData.length;
    //判断数组非空
    if (oldCapacity > 0 || elementData != DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        // 开始扩容 求扩容后数组容量
        int newCapacity = ArraysSupport.newLength(oldCapacity,
                   //最小需要增加的容量
                minCapacity - oldCapacity, 
                  // 旧容量的一半左右                                
                oldCapacity >> 1           );
        //调用copyof方法进行数组拷贝
        return elementData = Arrays.copyOf(elementData, newCapacity);
    } else {
        // 创建数组
        return elementData = new Object[Math.max(DEFAULT_CAPACITY, minCapacity)];
    }
}

// ArraysSupport类

 public static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;

  public static int newLength(int oldLength, int minGrowth, int prefGrowth) {
        
         // 扩容后数组容量 = 最小需要增加的容量 和 旧容量的一半左右 两者取最大值 + 旧容量
        int newLength = Math.max(minGrowth, prefGrowth) + oldLength;
        if (newLength - MAX_ARRAY_LENGTH <= 0) {
            // 新容量没有超过 Integer.MAX_VALUE - 8 就返回新容量
            return newLength;
        }
      // 长度超过了Integer.MAX_VALUE - 8, 此时采取需要增加几个容量就扩几个                //如果超过 Integer.MAX_VALUE 就报OutOfMemoryError 异常  
        return hugeLength(oldLength, minGrowth);
    }

private static int hugeLength(int oldLength, int minGrowth) {
        int minLength = oldLength + minGrowth;
     // 溢出
        if (minLength < 0) { // overflow
            throw new OutOfMemoryError("Required array length too large");
        }
        if (minLength <= MAX_ARRAY_LENGTH) {
            return MAX_ARRAY_LENGTH;
        }
        return Integer.MAX_VALUE;
    }

为什么在扩容是,需要与Integer.MAX_VALUE - 8比较,而不是Integer.MAX_VALUE

JVM虚拟机(Hotspot)在存储对象是还要存储对象头需要占用32字节。如果尝试分配更大的数组可能会导致OutOfMemoryError请求的数组大小超过虚拟机限制

ArrayList对于内存空间浪费 体现在需要在集合尾部预留一部分空间

1.2 LinkedList

List集合中链式存储的集合,底层采用双向链表(JDK1.6之前为双向循环链表),LinkedList还实现了Deque接口,可以当作双端队列来使用。既可以当栈使用,也可以当队列使用

链式存储最大特点就是在元素之间插入新元素或者删除元素不需要移动之后的元素位置,但是访问元素需要遍历整个链表,不能像ArrayList快速根据下标访问。

在日常使用集合的场景下,可以使用LinkedList时同时也可以使用ArrayList,且使用集合需要频繁遍历,因此ArrayList几乎可以取代LinkedList

由于需要存储直接前驱和直接后继,因此每个元素都需要多两个指针的开销

private static class Node<E> {
    E item;
    Node<E> next;
    Node<E> prev;

    Node(Node<E> prev, E element, Node<E> next) {
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

1.3 Vector

Vector在List集合中不常用,底层使用Object[] 存储,最大特点是线程安全的,通过在方法上加synchronized 关键字来保证线程安全,执行效率比较低

2. Queue

队列是数据结构中比较重要的一种类型,队列的特点是先进先出FIFO,Queue是单端队列,只能在一端添加元素,另一端移除元素,而Deque 是双端队列,在两端都可以进行增删操作。

常用实现类: ArrayDequePriorityQueueLinkedList

队列中增删查元素时根据 因容量问题返回的结果不同 分为两类,一类操作失败后抛出异常,另一类操作失败后返回

  • add() 添加元素,在队列满的情况下抛异常
  • offer()添加元素,在队列满的情况下返回false
  • remove()删除队列头元素,队列为空的情况下将抛异常
  • poll()删除队列头元素,在队列为空的情况下将返回null
  • element()返回队列的头元素,在队列为空的情况下,将抛异常
  • peek()返回队列的头元素,在队列为空的情况下返回null

2.1 ArrayDeque

底层采用动态数组+双指针,且元素不支持NULL

transient Object[] elements;

transient int head;

transient int tail;

扩容过程类似于ArrayList

2.2 PriorityQueue

优先级队列,底层采用动态数组存储数组,通过二叉堆数据结构来实现优先级高的先出队。不支持存储NULL,默认是小顶堆可以接收一个 Comparator 作为构造参数,从而来自定义元素优先级的先后。

transient Object[] queue; 

int size;

private final Comparator<? super E> comparator;

3. Set

无序集合,不允许存放重复元素,常用实现类有HashSetLinkedHashSetTreeSet

3.1 HashSet

HashSetSet集合最常用实现类,底层数据结构采用哈希表(数组+链表+红黑树)实现,相当于一个只有key的HashMap,元素无序且唯一,可以存储null元素。

无序性: 存储的元素在数组中是按照哈希值来决定位置

唯一性: 通过重写equals() 方法和 hashCode() 方法来保证元素的唯一性

public HashSet() {
    map = new HashMap<>();
}

(详细过程见后续文章Map集合)

3.2 LinkedHashSet

继承HashSet实现LinkedHashMap接口,底层由哈希表+双向链表实现,链表保证了元素的顺序与存储顺序一致,哈希表保证了元素的唯一性。常用的缓存淘汰策略LRU算法的普通版本就是这样实现的。

3.3 TreeSet

底层数据结构采用二叉树来实现,元素唯一且有序,唯一性需要重写hashCodeequals()方法,二叉树结构保证了元素的有序性。

排序分为自然排序(存储元素实现Comparable接口)和自定义排序(创建TreeSet时,传递一个自己实现的Comparator对象)

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

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

相关文章

UE4 Cook指定平台资源

内容烘焙 | 虚幻引擎文档 (unrealengine.com) 虚幻引擎以内部使用的特定格式存储内容资源&#xff0c;如PNG用于存储纹理 数据&#xff0c;WAV用于音频数据。但是&#xff0c;该内容需要针对各平台转换为不同的格式&#xff0c; 因为平台使用专有格式&#xff0c;或者平台不支…

Revit中“幕墙网格”编辑斜向网格和柱断墙梁

一、Revit中“幕墙网格”编辑斜向网格 我们可以为幕墙添加任意间距的水平和垂直的网格线&#xff0c;但是对于斜向网格线我们却只能通过设置其实例属性中的角度来控制其生成一系列等间距的斜向网格&#xff0c;那么如果遇到不等间距的斜向网格线我们应该如何绘制呢? 首先通过设…

博宜OJ练习题基础题目中个别问题的题(欢迎一起讨论)

中国博宜练习题个别问题&#xff0c;望讨论前言题目1解题思路提交后正确代码&#xff1a;个人写的错误代码题目2正确代码2个人写的错误代码2以上是个人目前遇到的两个问题&#xff0c;不知道是直接使用“max”函数的问题 还是什么&#xff0c;如果是“max”函数问题第一个测试点…

多线程与高并发(二)

【锁的底层实现】&#xff1a; 【 简介 】&#xff1a; JDK早期的时候是重量级的 &#xff0c; 会去找OS系统申请锁 &#xff0c;效率非常低。 后来的改进——《锁升级过程》。 【锁升级过程】&#xff1a; sync( Object ) 【偏向锁】&#xff1a; markword记录这个线程ID&…

[附源码]Python计算机毕业设计Django基于JEE平台springbt技术的订餐系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

以太网 MSTP多实例生成树的简介、MSTP与RSTP、STP之间的联系、MSTP BPDU格式介绍、MSTP关键名词介绍)

2.12.0 以太网 MSTP多实例生成树&#xff08;简介、MSTP与RSTP、STP联系、MSTP BPDU格式、MSTP关键名词介绍&#xff09; 主要参考&#xff1a;华为S2750, S5700, S6700 V200R005(C00&C01&C02&C03) 产品文档 《MSTP基本概念》 MSTP快速生成树简介MSTP关键名词介绍1…

springboot+mybatis+mysql实现的个人博客管理系统(功能包含登录,栏目管理、文章管理、评论管理、系统设置、用户管理、发布博客、评论等)

博客目录springbootmybatis实现的个人博客管理系统实现功能截图系统功能使用技术代码完整源码springbootmybatis实现的个人博客管理系统 本系统是一个个人博客管理系统&#xff0c;比较新的框架springbootmybatis实现&#xff0c;分为普通用户和管理员&#xff0c;普通用户可以…

【软件测试】测试人接手新应用程序怎么测?看看这几个方法......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 应用程序很复杂的&a…

三、数据链路层(三)差错控制

目录 3.1检错编码 3.1.1奇偶校验码 3.1.2循环冗余码&#xff08;CRC&#xff09; 3.2纠错编码 3.2.1海明码 传输差错可分为两种&#xff1a; 位错&#xff1a;帧中某些位出现了差错&#xff0c;也称比特差错、误码。帧错&#xff1a;帧的丢失、重复或失序等错误。 通常利…

面试题:数据结构和算法

1、时间复杂度解释一下 算法的时间复杂度&#xff0c;用来度量算法的运行时间&#xff0c;记作: T(n) O(f(n))。它表示随着 输入大小n 的增大&#xff0c;算法执行需要的时间的增长速度可以用 f(n) 来描述。 当 T(n) c&#xff0c;c 为一个常数的时候&#xff0c;我们说这个…

[附源码]Python计算机毕业设计Django基于vue+mysql开发的考试系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Java web 2022跟学尚硅谷(九)书城项目

Java web 2022跟学尚硅谷九书城项目需求分析数据库设计ER图书城1.0简单部署项目类图相关代码UserControllerUserDAOImplUserDAOBookCartItemOrderOrderItemUserUserServiceImplUserServiceapplicationContext.xml书城1.1实现功能1. 用户登录2. 首页图书列表展示3. 首页价格筛选…

Vue3-ElemenPlu,全栈开发后台系统1-1-2-9第一章,第二章前端系统架构设计

Vue3+ElementPlus Lo2+MongoDB 菜单按钮权限,JWT认证,审批流,常规的CRUD,模块化,组件化 技术栈: 架构设计,vue3全家桶,koa2, 权限: Role-Based A

[附源码]Node.js计算机毕业设计辅导员班级量化管理系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

IMX6启动流程

目录 1. 流程图 2. u-boot.imx的构造 1. 流程图 正常情况下&#xff0c;一台IMX6设备的启动路径就是图中自上而下最左边那条路&#xff1a; 启动/复位后先检查CPU的ID(每颗芯片独一无二) ------> 检查复位状态(有没有按下复位键) ------> 检查boot模式(mmc? USB? SPI…

ARM寄存器组织(常见专用寄存器、控制寄存器CPSR)

目录 一、寄存器的概念 1、什么是寄存器&#xff1f; 2、寄存器的分类 3、不同工作模式下使用的寄存器 二、常见专用寄存器 1、R15&#xff08;PC,Program Counter&#xff09; 2、R14&#xff08;LR,Link Register&#xff09; 3、R13&#xff08;SP,Stack Pointer&am…

FineReport大数据分析工具- 统一切换轮播图表接口

1. 概述 1.1 版本 报表服务器版本 功能变动 11.0 - 1.2 预期效果 某些场景下&#xff0c;需要让一张报表内的多个轮播图表同时切换。那么该如何实现呢&#xff1f;效果如下图所示&#xff1a; 1.3 实现思路 按钮添加点击事件&#xff0c;通过 JS 脚本调用接口统一切换轮播…

【模拟电路】431基准电压源

项目简介 概述 431电压基准芯片为3脚稳压集成电路&#xff0c;431基准电压源具有良好的热稳定性能的&#xff0c;三端可调分流&#xff0c;也被称为电压调解器或三端取样集成电路。凭借体积小、重量轻、精度高、稳定可靠、基准电压精密可调、输出电流大&#xff0c;且价格便宜…

LightDock、PatchDock蛋白蛋白对接软件linux端命令行使用

本文实在ubuntu下操作 DDB1-CRBN.pdb 、brd4.pdb 是需要对接的两个pdb蛋白文件 1、PatchDock 网页版&#xff1a;https://bioinfo3d.cs.tau.ac.il/PatchDock/php.php PatchDock有网页版&#xff0c;如下&#xff1b;软件版需要申请获取下载链接 参考&#xff1a;https://bioi…

QT4.8.7 打开Mupdf

一.Win10环境 1.Win10 Visual Studio 2017 安装 这个直接安装了 a.打开mupdf 源码 b.编译源码 参考这几个贴子 在Qt中调用Mupdf库进行pdf显示 mupdf-1.17.0 源代码编译、下载 qt vc pdf阅读器 我用的是mupdf-1.11-source的&#xff0c;用VS2017打开会有这个问题 c.修改配…