ArrayList扩容机制JDK1.8

ArrayList扩容机制JDK1.8本题的所有的讲解都是基于JDK8这道题考察了ArrayList的构造器和对扩容机制的了解,本篇博客基于此出发讲解ArrayList的扩容机制想要做出这道题必须了解ArrayList的构造函数,ArrayList的构造函数总共有三个:ArrayList()构造一个空的数组。JDK7中构造一个初始容量为10的空列表但是JDK8中只是构造一个空的数组ArrayList(Collection<?extendsE>c)构造一个包含指定collection的元素的数组,这些元素是按.

大家好,又见面了,我是你们的朋友全栈君。

本题的所有的讲解都是基于JDK8

在这里插入图片描述

这道题考察了ArrayList的构造器和对扩容机制的了解,本篇博客基于此出发讲解ArrayList的扩容机制

想要做出这道题必须了解ArrayList的构造函数,ArrayList的构造函数总共有三个:

  1. ArrayList()构造一个空的数组。JDK7中构造一个初始容量为10的空列表但是JDK8中只是构造一个空的数组
  2. ArrayList(Collection<? extends E> c)构造一个包含指定 collection 的元素的数组,这些元素是按照该 collection 的迭代器返回它们的顺序排列的。
  3. ArrayList(int initialCapacity)构造一个具有指定初始容量的空数组。

我们重点来看这两个ArrayList(int initialCapacity)ArrayList()构造函数

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = { 
   };
public ArrayList() { 
   
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

初始化一个空数组,这是JDK8不同于之前版本的地方

public ArrayList(int initialCapacity) { 
   
    if (initialCapacity > 0) { 
   
        this.elementData = new Object[initialCapacity];
    } else if (initialCapacity == 0) { 
   
        this.elementData = EMPTY_ELEMENTDATA;
    } else { 
   
        throw new IllegalArgumentException("Illegal Capacity: "+
                                           initialCapacity);
    }
}

对于形参initialCapacity判断,如果大于0那么就声明一个和形参一样大小的数组。了解到这里似乎这道题的正确答案也出来了即选择A,并没有发生扩容

但是作为一名合格的程序员要有探索精神,题目提到了扩容,既然ArrayList底层是一个数组,那么就肯定会满,什么时候发生扩容呢?

//1.add方法为添加元素在数组末尾
public boolean add(E e) { 
   
    //确保数组容量 size指向数组的末尾
    ensureCapacityInternal(size + 1);
    //在完成添加之前要确保数组长度足够
    elementData[size++] = e;
    return true;
}
//3.elementData为ArrayList底层维护的数组,minCapacity为此时数组的大小
private static int calculateCapacity(Object[] elementData, int minCapacity) { 
   
    //如果数组为初始化的值,就初始化数组容量为10(空参的构造方法下首次添加)
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { 
   
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}
//2.minCapacity表示此时数组的大小
private void ensureCapacityInternal(int minCapacity) { 
   
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//4.minCapacity表示此时数组的大小
private void ensureExplicitCapacity(int minCapacity) { 
   
    modCount++;
    //如果此时数组容量的大小不够就扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

源码读到这里,我们明白了,当我们每次向ArrayList添加元素的时候,都会首先确保数组容量够放下元素如果不够就会 grow(minCapacity)调用扩容函数,那么秉承着探索的精神,原本大小的数组扩容之后变成多大了呢?还得继续看源码

//扩容源码
private void grow(int minCapacity) { 
   
    //获取当前数组的长度
    int oldCapacity = elementData.length;
    //>>右移相当于整除2,新容量相当于就旧容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //如果扩容后的容量还不够那么就以需要的容量为新容量
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    //如果新容量已经超过最大容量了,那么就直接使用最大容量
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    //讲新容量的数组拷贝
    elementData = Arrays.copyOf(elementData, newCapacity);
}

源码大致读完后,我们明白了ArrayList的自动扩容机制,每次新添加元素的时候都会判断是否能够容下,如果不够就会发生扩容,扩容的大小为原大小的1.5倍数,明白这些以后让我们看看下面这段程序扩容了几次呢??容量是多少呢?

ArrayList<Integer> arrayList = new ArrayList<Integer>(20);
for(int i=1;i<=50;i++) { 
   
     arrayList.add(i);
}

前20次添加不会发生扩容,当21元素添加时数组容量从20扩容到30,当添加31元素时数组容量从30扩容到45,当添加46元素时数组容量从45扩容到67

ArrayList扩容机制JDK1.8

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/133209.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • ali-tomcat部署war包去掉工程名[通俗易懂]

    ali-tomcat部署war包去掉工程名[通俗易懂]遇到的问题:在ali-tomcat中部署war包时,在deploy文件夹下,有时会解压出一个带工程名的文件夹,有时只解压出一个ROOT文件夹,期望不带工程名,方便请求。解决方式:在/conf/server.xml的标签添加以下内容,就可以直接通过http://ip:port/请求到工程了,但是deploy下会有工程名和ROOT两个文件夹(待续。。。)

  • ettercap的使用帮助文档 官方man page的个人理解

    ettercap的使用帮助文档 官方man page的个人理解原英文的帮助文档可以在http://linux.die.net/man/8/ettercap查看或者在安装有ettercap的Linux终端输入”manettercap”查看多数以我自己的理解的方式翻译,不是很理解的地方翻译过来的可能会有很多不对的地方如果对我翻译的内容有不一样的看法,欢迎交流。Nameettercap0.7.5-Amultipurposesniffer/co

  • delphi中listview选择整行

    delphi中listview选择整行修改RowSelect属性为真

  • win32 api函数_c调用webapi接口

    win32 api函数_c调用webapi接口前言如果要在Windows上面写程序,就不得不了解一些Win32Api的使用,Win32Api在C/C++的环境中使用非常的方便,直接调用头文件<Windows.h>使用就行了,但在C#中不会这么简单,需要在指定的模块之中导入想要的Win32,下面我们来学习一下如何在C#之中使用Win32Api…在测试Win32Api之前,我先教大家如何获取有窗口的进程信息,代码如下:有窗口的进程,它的窗口句柄不会为0,所以我们只需在所有运行的程序之中判断一.

    2022年10月11日
  • 免费 UML 工具

    免费 UML 工具选取了四款UML工具:astah经常看到网上的黄色背景就是这个软件画的,最后一个免费的社区版本是:astahcommunity7.2安装包大小50M以下三个均为免费版本:SoftwareIdeasModeler可以画序列图,安装包很小,只有十几兆,而且提供便携版下载Modelio这是一个大型的软件,安装包300+MBModelio是由位于法国巴黎的Modeliosoft开发的开源UML工具。它支持UML2和BPMN标准。BOUML看起来…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号