解析从源码分析常见的基于Array的数据结构动态扩容机制的详解

解析从源码分析常见的基于Array的数据结构动态扩容机制的详解

什么是动态扩容机制

动态扩容机制是指,当一个数据结构达到其容量限制时,自动增加容量大小以继续存储新的数据。在动态扩容时,需要考虑到时间和空间的平衡,因为扩容需要分配新的内存空间,在处理大量数据时,需要尽可能减少空间浪费和分配内存的时间消耗。

基于Array的数据结构

Array是一种连续存储的数据结构,可以通过数组下标来访问数据。基于Array的数据结构通常会预先分配一段连续的内存空间作为存储空间,这段空间的大小是有限制的,达到这个限制后需要进行动态扩容。

常见的基于Array的数据结构

常见的基于Array的数据结构包括ArrayList、Deque和Queue等。

示例1:ArrayList

ArrayList是Java中常用的数据结构之一,它是基于Array实现的一种动态数组。当ArrayList中元素的数量超过数组容量限制时,就需要对其进行动态扩容。

在Java中,ArrayList内部维护了一个通过数组实现的elementData数组,当元素的数量超过了数组长度时,需要进行扩容,扩容的实现如下:

/**
 * 扩容方法
 * newCapacity 扩展空间的大小
 */
private void grow(int newCapacity) {
        // 当前容量
        int oldCapacity = elementData.length;
        // 扩容后数量
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 如果扩容后元素数量超出容量限制则直接使用Integer.MAX_VALUE为新大小
        if (newCapacity - minCapacity < 0) {
            newCapacity = minCapacity;
        }
        // 复制元素
        elementData = Arrays.copyOf(elementData, newCapacity);
}

可以看到,在ArrayList中,扩容时,首先会将旧数组的长度增加50%,然后再根据minCapacity设置扩容后的新长度,如果minCapacity的值小于新长度,则直接将新长度设置为Integer.MAX_VALUE。

示例2:Deque和Queue

Deque是双端队列的一种实现,Queue是队列的一种实现,它们是通过Array实现的。

在Java中,ArrayDeque是Deque的一种实现方式,它的底层是一个循环数组,当数组的大小不足以容纳新的元素时,ArrayDeque采用双倍大小动态扩容机制进行扩容,其扩容实现如下:

/**
 * 扩容方法
 */
private void doubleCapacity() {
    int addCapacity;
    if (head < tail) {
        addCapacity = elements.length;
    } else {
        // 头尾都是指向数组的开头,数组末尾有空闲位置,这种情况下扩容元素个数是elements.length - head
        // 头尾相对位置不变,数组末尾无空余位置,这种情况下扩容元素个数是elements.length - head + tail
        addCapacity = elements.length - head + tail;
    }

    // 根据原始数组大小和新增元素个数,计算出新的数组大小
    int newCapacity = elements.length << 1;
    if (newCapacity < 0) {
        throw new IllegalStateException("Sorry, deque too big");
    }
    Object[] newElements = new Object[newCapacity];
    // 复制旧的数组,并修正新数组的起始位置
    System.arraycopy(elements, head, newElements, 0, addCapacity);
    System.arraycopy(elements, 0, newElements, addCapacity, tail);
    elements = newElements;
    // 重置头部和尾部的位置
    head = 0;
    tail = addCapacity;
}

可以看到,在Deque和Queue实现中,扩容时,首先会判断表头和表尾对应的元素位置,然后计算出新数组的长度,并将旧的数据复制到新的数组中。最后,将队列的头部和尾部指针指向新的数组的头尾位置。

结语

基于Array的数据结构的动态扩容机制可以提高数据结构的效率和容量,但扩容时需要考虑到时间和空间的平衡,避免浪费内存和增加内存消耗。通常,动态扩容机制都是内部实现,我们只需要了解其原理和实现过程即可。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:解析从源码分析常见的基于Array的数据结构动态扩容机制的详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • Java数据结构之队列(动力节点Java学院整理)

    Java数据结构之队列(动力节点Java学院整理) 队列是一种有序列表,在其中所有插入操作必须在后端进行,而所有的删除操作必须在前端进行的数据结构。这种结构有时被称为先进先出(FIFO)。 队列的分类 普通队列:队列和栈一样,都是只能在一端进行插入操作,在另一端进行删除操作的特殊线性表。队列的特点是:先进先出。适用于数据必须按照插入顺序处理的必要场合。 双端…

    数据结构 2023年5月17日
    00
  • Redis高效率原因及数据结构分析

    Redis高效率原因及数据结构分析 Redis高效率的原因 Redis是一款高性能、高可靠性的内存数据库,其高效率的原因主要体现在以下几个方面: 1. 内存存储 Redis数据完全存储在内存中,而不是像传统的关系型数据库一样存储在磁盘中。内存的读写速度要远远快于磁盘的读写速度,因此Redis在数据读写时的速度非常快,能够达到每秒钟数百万次的读写操作。 2. …

    数据结构 2023年5月17日
    00
  • 浅谈iOS 数据结构之链表

    浅谈iOS 数据结构之链表 在计算机科学中,链表是一种数据结构,用于存储一系列按顺序排列的元素。链表的一个关键点是它不需要连续的内存空间来存储元素,相反,每个元素由一个指向下一个元素的指针组成。在iOS开发中,链表在各种场景下都有所应用,如UITableView和UICollectionView的数据源等。本文将详细讲解链表的基本知识和使用技巧。 链表的基本…

    数据结构 2023年5月17日
    00
  • c#解析jobject的数据结构

    下面我将从以下几个方面,详细讲解如何使用C#解析JObject的数据结构。 1. 什么是JObject JObject 是 JSON.NET 库中的一个类,用于处理Json格式数据。它表示一个 JSON 对象,可以通过键值对的形式来描述一个 JSON 对象,并在其中包含 JSON 数组。JObject对象是动态类型,允许在运行时动态添加、修改或删除对象的属性…

    数据结构 2023年5月17日
    00
  • C语言数据结构之简易计算器

    C语言数据结构之简易计算器攻略 简介 这是一个基于C语言的简易计算器,可以实现加、减、乘、除四个基本运算。 实现步骤 首先,需要声明四个变量,分别表示运算符、被加数、被减数、被乘数和被除数。 char op; double n1, n2, result; 然后,需要通过scanf()函数获取用户输入的运算符和数字。 printf(“请输入运算符和数字:\n”…

    数据结构 2023年5月17日
    00
  • C语言实现通用数据结构之通用椎栈

    C语言实现通用数据结构之通用椎栈 概述 通用椎栈(Generic Linked List Stack),简称GLL Stack,是一种通用的数据结构,能够以动态的方式存储和访问任意类型的数据。GLL Stack 采用链表实现,可以进行进栈(push)、出栈(pop)、查看栈顶元素(peek)、判断栈是否为空(isEmpty)等基本操作。 基本操作 数据结构定…

    数据结构 2023年5月17日
    00
  • C语言数据结构哈希表详解

    C语言数据结构哈希表详解 什么是哈希表? 哈希表(Hash Table)是一种采用散列函数(hash函数)将数据映射到一个固定长度的数组中,并且以 O(1) 的时间复杂度进行数据插入、查找、删除操作的数据结构。哈希表主要由以下三个组成部分构成:- 数组:用于存储映射到对应下标上的数据。- 散列函数:将数据映射到数组下标上的规则。- 冲突处理方式:当不同的数据…

    数据结构 2023年5月16日
    00
  • 牛客小白月赛71

    A.猫猫与广告 题目: 分析: 只需考虑c * d的矩阵竖着摆和横着摆两种情况。本题提示了考虑两矩阵对应边平行的情况,实际上可以证明倘若能斜着放,那么一定可以横着放或竖着放,证明方式可已通过构造三角形来证明a* b的矩阵的长宽一定小于c * d矩阵的长宽。 code: #include <iostream> #include <cmath&…

    算法与数据结构 2023年4月25日
    00
合作推广
合作推广
分享本页
返回顶部