arraylist 的扩容机制_每天都用ArrayList,你读过它的源码么?

0b761b01e968274cc6ce5043de2b0f13.png

作者:陌北有棵树,玩Java,架构师社区合伙人!

【一】关于扩容

如果没有指定初始容量,则设置为10

/**
 * Default initial capacity.
 */
private static final int DEFAULT_CAPACITY = 10;

ArrayList的扩容比较简单,容量扩为之前的1.5倍
/**
 * Increases the capacity to ensure that it can hold at least the
 * number of elements specified by the minimum capacity argument.
 *
 * @param minCapacity the desired minimum capacity
 */
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    if (newCapacity - minCapacity 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    elementData = Arrays.copyOf(elementData, newCapacity);
}

【二】关于拷贝

源码中用到的数组复制的两个方法分别是:System.arraycopy()和Arrays.copyOf()

一句话总结二者区别:Arrays.copyOf()可以看做是受限制的System.arraycopy()

Arrays.copyOf()是系统自己创建一个数组,再调用System.arraycopy()复制

public static  T[] copyOf(U[] original, int newLength, Class extends T[]> newType) {@SuppressWarnings("unchecked")
    T[] copy = ((Object)newType == (Object)Object[].class)
        ? (T[]) new Object[newLength]
        : (T[]) Array.newInstance(newType.getComponentType(), newLength);
    System.arraycopy(original, 0, copy, 0,
                     Math.min(original.length, newLength));return copy;
}

System.arraycopy()需要传入一个目标数组作为参数,同时可以指定拷贝的起点和拷贝的长度

public static native void arraycopy(Object src,  int  srcPos,
                                    Object dest, int destPos,int length);

各个参数的含义:

src - 源数组。
srcPos - 源数组中的起始位置。
dest - 目标数组。
destPos - 目标数据中的起始位置。
length - 要复制的数组元素的数量。

同时要注意的是,上述两个拷贝方法都是浅拷贝,关于深拷贝和浅拷贝,后续会做详细说明。

【三】关于Fail-Fast

Fail-Fast是非线程安全的集合,实现的一种错误机制。但不能百分百得到保证,只是尽最大努力抛出ConcurrentModificationException。

什么时候产生Fail-Fast
ArrayList中如何实现Fail-Fast
两个变量:modCount和expectedModCount
只要涉及到数组个数改变的方法,都会导致modCount的改变(add、remove、clear)
当发现expectedModCount和modCount不一致,就会抛出ConcurrentModificationException
所以,Iterator在遍历时,是不允许被迭代的对象被改变的

final void checkForComodification() {
    if (modCount != expectedModCount)
        throw new ConcurrentModificationException();
}

如何避免Fail-Fast:用CopyOnWriteArrayList代替ArrayList

【四】关于ArrayList中删除元素

错误的删除方式一:for循环遍历删除

public void testRemove() {
   List integers = new ArrayList<>(5);
   integers.add(1);
   integers.add(2);
   integers.add(2);
   integers.add(4);
   integers.add(5);for (int i = 0; i       if (integers.get(i) % 2 == 0) {
         integers.remove(i);
      }
   }
   System.out.println(integers);
}

这段代码的输出是 [1,2,5]

因为在remove方法执行的时候,删除第一个“2”,会更新后面的索引值,数组变为[1,2,4,5],这样会导致第二个“2”不会被删除

错误的删除方式二:使用Iterator遍历,但仍用ArrayList的remove方法

public void testRemove(){
   List strings = new ArrayList<>();
   strings.add("a");
   strings.add("b");
   strings.add("c");
   strings.add("d");
   Iterator iterator = strings.iterator();while (iterator.hasNext()){
      String next = iterator.next();
      strings.remove(next);
   }
   System.out.println(strings);
}

会抛出ConcurrentModificationException,参见上述的Fail-Fast机制

正确的删除方法:使用Iterator的remove方法

public static void main(String[] args) {
   List intList = new ArrayList();
   Collections.addAll(intList, 1, 2, 3, 5, 6);
   Iterator it = intList.iterator();while(it.hasNext()) {
      Integer value = it.next();if(value == 3 || value == 5) {
         it.remove();
      }
   }
   System.out.println(intList);
}

长按订阅更多精彩▼

c3f2315f71113ffe41fa508f066f9376.png

如有收获,点个在看,诚挚感谢9b6884a58acbdbe806c33a5187b90681.png

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

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

相关文章

JAVA入门级教学之(IDEA工具的快捷键和简单设置)

1.字体font file-->settings-->输入font-->设置字体样式以及字号大小 2.快速生成main方法 psvm 3.快速输出Systm.out.println(); sout 4.删除一行 ctrly 5.怎么运行 代码删右键run 或者点击右上角箭头 shiftf10(不同电脑可能不一样) 6.左侧窗口中的列表怎么展开…

java selenium_selenium 常见面试题以及答案(Java版)

1.怎么 判断元素是否存在&#xff1f;判断元素是否存在和是否出现不同&#xff0c; 判断是否存在意味着如果这个元素压根就不存在&#xff0c; 就会抛出NoSuchElementException这样就可以使用try catch&#xff0c;如果catch到NoSuchElementException 就返回false2.如何判断元素…

关于HTML的盒子的一些小问题

最近在开发的时候发现一个小问题&#xff0c;<DIV>我们很熟悉的一个盒子元素 关于他的描述 1.按照我们正常人的思维逻辑 编写好一个DIV盒子&#xff0c;然后再在盒子里面添加边框border、内边距padding、内容&#xff0c;这是我们的思维逻辑 但是DIV的编写会随着你添加…

语义网络分析图怎么做_怎么去分辨化工壶,光说可能大家还是会有疑惑,所以做了几个图...

网友们经常会拿一些壶出来&#xff0c;拍图给我看&#xff0c;问我会不会是化工壶&#xff0c;说到底&#xff0c;还是不放心自己手头上的紫砂壶&#xff0c;怕对自身健康造成影响&#xff0c;在这里&#xff0c;小编特地编辑这一段&#xff0c;教大家怎么去分辨化工壶&#xf…

CSS3特效之转化(transform)和过渡(transition)

CSS3特效之转化&#xff08;transform&#xff09;和过渡&#xff08;transition&#xff09; 在对动画深入之前&#xff0c;我们需要先了解它的一些特性&#xff0c;CSS3的转化&#xff08;transform&#xff09;和过渡&#xff08;transition&#xff09;。有人可能会有疑…

java如何保证redis设置过期时间的原子性_分布式锁用 Redis 还是 Zookeeper

在讨论这个问题之前&#xff0c;我们先来看一个业务场景&#xff1a;系统A是一个电商系统&#xff0c;目前是一台机器部署&#xff0c;系统中有一个用户下订单的接口&#xff0c;但是用户下订单之前一定要去检查一下库存&#xff0c;确保库存足够了才会给用户下单。由于系统有一…

转 安卓解决 IDEA 下 struts.xml 中 extends=“struts-default“ 报红的问题

解决 IDEA 下 struts.xml 中 extends"struts-default" 报红的问题 现象 在IDEA中配置struts.xml时 extends"struts-default" 报红&#xff0c;配置拦截器时属性无预选项提示&#xff0c;也爆红。 struts.xml本身的配置并没有错误。 解决办法 CtrlShiftAl…

系统新模块增加需要哪些步骤_人工智能之父的问题解决策略:模块化

最近主题阅读马文明斯基(Marvin Minsky) 和西摩佩珀特(Seymour Papert)两位人工智能大师&#xff0c;关于思维&#xff0c;关于教育的书籍。其中马文被称为「人工智能之父」。两人都非常重视过程模块化。复杂问题的解决需要系统性&#xff0c;也很少一次做对&#xff0c;要通过…

小白学Linux(一:开门见山)

目录 1.javaEE&#xff0c;先搭环境再敲码 2.Linux大数据 3.Python 4. Linux的学习方向 5. Linux的进阶段位 6.下面开始进入实际操作环节 第一步.安装虚拟机软件 第二步.在虚拟机里面安装一个别人开发好的Centos系统&#xff08;可以在此系统中写Linux指令&#xff0c;…

vb net 模拟 ctrl+c_8款优秀的.NET开发工具,收藏了

NET是一个重要的应用程序开发平台&#xff0c;因为它安全、稳定、易于学习和实现。今天小编给就给大家介绍8款优秀的.NET开发工具&#xff0c;有需要的小伙伴可以收藏转发哦。1、ChocolatyChocolaty是一个Windows软件包管理器&#xff0c;这个工具的重要之处在于&#xff0c;它…

卸载后以前拍的视频会删除吗_可立拍!苹果自己的视频编辑App是一个被忽视的好工具...

手机预装应用总是不如三方产品&#xff1f;看到这个问题&#xff0c;你是不是会下意识反驳&#xff1a;iPhone自带 app 就很好用啊&#xff01;的确如此&#xff0c;iPhone 的《Pages》《备忘录》&#xff0c;这些 app 的优秀表现改变了不少人「拿到新机就想卸载预装应用」的想…

解决:Linux中的CentOS 7的火狐浏览器不能访问服务器

今天安装CentOS 7的时候配置好环境&#xff0c;发现火狐不能连网 分析了一些可能是我的虚拟机网络配置没开&#xff0c;因此我总结了两个方法 1.检查虚拟机的编辑--》虚拟网络编辑器--》看看是否是NAT连接 2.搜索计算机的服务--》找到VMware DHCP Service和VMware NAT Servi…

pyqt5 自定义控件_PyQt5学习笔记(十六)Pyinstaller打包与SQLite数据库

终于到了最后一章了QAQ&#xff0c;第一次写4万字以上的笔记分享&#xff0c;最近也在忙科创和CV的比赛&#xff0c;所以笔记会显得比较粗糙。其实吧分享这个笔记很大一部分是为了让自己记得更牢&#xff0c;网上翻阅自己的笔记也方便&#xff0c;如果有讲解注释不清楚的地方欢…

依赖第三方库时出现的问题:Manifest merger failed : uses-sdk:minSdkVersion 15 cannot be smaller than version 16

导入第三方库时出现了sdk版本不兼容问题 为我们app的module所支持的sdk最低版本与依赖module的sdk最低版本不一致 把15--》16即可

Linux基本目录结构

上一步我们已经搭建好实验环境了&#xff0c;这一节就来实际操作一下&#xff0c;到底什么是CentOS&#xff0c;到底什么是Linux操作系统&#xff0c;写什么&#xff0c;如何去做&#xff0c;如何去打开&#xff0c;下面我们带着这些疑惑展开这一节 1.打开终端&#xff0c;有些…

解决:VMware DHCP Service 服务无法启动

今天在布置项目的时候发现VMware DHCP Service 服务无法启动&#xff0c;连网络也连接不了 解决办法是 搞定 解决后验证Linux又可以连接上网络了

bmp文件格式_一次性解决CAD转换成BMP格式图片的问题

关于BMP格式图片&#xff0c;可能很多小伙伴都遇到得比较多&#xff0c;但在这里还是稍微解释一下吧。它是Windows操作系统中的标准图像文件格式&#xff0c;大家都知道BMP格式的图片都非常大&#xff0c;那是因为它没有经过任何压缩。当然&#xff0c;关于BMP文件当中蕴含着哪…

Linux如何配置网络IP地址

首先&#xff0c;脑子思路一定要清晰我们为什么要配置ip地址&#xff0c;我们的电脑一般是一个物理网卡&#xff0c;那么按照正常情况&#xff0c;我们的虚拟机里的Linux是和windows共享同一个物理网卡的&#xff0c;所以很正常&#xff0c;一个物理网卡不可能仅仅只有一个ip地…

shell 字典_腾讯T4周末不陪对象,就为了手打这份shell编程笔记

这个周末&#xff0c;为了某些原因&#xff0c;我把shell编程的一些基础知识进行了相应的整理&#xff0c;这里分享给大家&#xff0c;大家在看的时候&#xff0c;有什么问题可以在下方评论区给我留言呀&#xff0c;欢迎转发自己纯手打&#xff0c;原创不易&#xff0c;谢谢支持…

Linux如何从普通用户切换到root用户

第一步&#xff1a;打开终端 pwd&#xff1a;Print Working Directory &#xff08;查看当前路径&#xff09; 默认安装完成之后并不知道root用户的密码&#xff0c;那么如何应用root权限呢&#xff1f; (1)sudo 命令 这样输入当前管理员用户密码就可以得到超级用户的权限…