文档章节

ArrayList 初探

z2
 z2
发布于 2017/07/20 13:32
字数 615
阅读 2
收藏 0

一.初始化 底层是一个私有的未持久化的对象数组,无参构造函数情况下,jdk 1.6版本下,底层数组大小为10,jdk1.7版本数组大小为0;如果构造函数自定义容量大小或者参数为集合引用是,数组大小为自定义大小或者集合元素个数。

private transient Object[] elementData;

二. 自动扩容

private void ensureCapacityInternal(int minCapacity) {
    if (elementData == EMPTY_ELEMENTDATA) {
        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
    }

    ensureExplicitCapacity(minCapacity);
}

如果elementData是null,则扩容取 DEFAULT_CAPACITY 和 minCapacity 中较大的值。如果它minCapacity 小于 DEFAULT_CAPACITY 这个方法会按 DEFAULT_CAPACITY 去扩容。

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}


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);
}

private static int hugeCapacity(int minCapacity) {
    if (minCapacity < 0) // overflow
        throw new OutOfMemoryError();
    return (minCapacity > MAX_ARRAY_SIZE) ?
        Integer.MAX_VALUE :
        MAX_ARRAY_SIZE;
}
  1. “>>1”,其实相当于除以2

  2. newCapacity 是 当前容量的 1.5 倍 newCapacity = oldCapacity + (oldCapacity >> 1)

  3. newCapacity 小于 minCapacity,则新容量 newCapacity = minCapacity

  4. newCapacity 超过数组的最大值 MAX_ARRAY_SIZE newCapacity = (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE

三.线程不安全

    //添加元素e    
    public boolean add(E e) {    
        // 确定ArrayList的容量大小    
        ensureCapacity(size + 1);  // Increments modCount!!    
        // 添加e到ArrayList中    
        elementData[size++] = e;    
        return true;    
    }    

赋值语句为:elementData[size++] = e,这条语句可拆分为两条:

  1. elementData[size] = e;
  2. size ++; 在单线程运行的情况下,如果 Size = 0,添加一个元素后,此元素在位置 0,而且 Size=1;
    而如果是在多线程情况下,比如有两个线程,线程 A 先将元素存放在位置 0。但是此时 CPU 调度线程A暂停,线程 B 得到运行的机会。线程B也向此 ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。然后线程A和线程B都继续运行,都增加 Size 的值。
    那好,现在我们来看看 ArrayList 的情况,元素实际上只有一个,存放在位置 0,而 Size 却等于 2。这就是“线程不安全”了

四.线程安全解决办法

1、继承Arraylist,然后重写或按需求编写自己的方法,这些方法要写成synchronized,在这些synchronized的方法中调用ArrayList的方法。

2、List list = Collections.synchronizedList(new ArrayList()); 效率低下

© 著作权归作者所有

共有 人打赏支持
下一篇: Numpy函数
z2

z2

粉丝 1
博文 12
码字总数 5379
作品 0
成都
私信 提问
ArrayList 底层数组扩容原理

原文出处:清浅池塘 ArrayList部分一共五篇文章了,并且引入了时间复杂度来分析,强烈建议大家一定要按顺序阅读,本文是第2篇,相关文章分别是: 1、ArrayList初始化 – Java那些事儿专栏 再...

清浅池塘
2017/12/02
0
0
集合框架2-ArrayList源码初探

由于笔者能力有限,本文也是学习的过程。部分内容可能会跳过,也希望大家可以不吝指导!~ 源码版本JDK1.8  数组是最常用的数据结构,相信大家对数组以及由数组实现的ArrayList的使用已经非常...

偏偏注定要落脚丶
2017/11/08
0
0
Jquery File upload 初探

官网:https://blueimp.github.io/jQuery-File-Upload/ 可以看到官方提供了几种不同的方案:我用的是basic plus ui 的样式 源码直接从github上下载即可: 要用到自己的项目里面,还是要注意几...

LonnyDong
2016/04/15
147
0
涨姿势:深入 foreach循环

foreach 循环 初探 我们知道集合中的遍历都是通过迭代(iterator)完成的。 也许有人说,不一定非要使用迭代,如: 这种方式对于基于链表实现的List来说,是比较耗性能的。 因为get(int i)方...

一只阿木木
06/13
0
0
XStream 初探,很给力

主要代码 (maven)所续的pom文件: 注意事项:如果想在java 项目中运行这个需要添加一些关联的包不然的话会报一个:

史上最强的弟子
2016/11/10
19
0

没有更多内容

加载失败,请刷新页面

加载更多

开源软件会被云杀死吗 ?

本文转载云头条,原作者:Michael Stiefel是Reliable Software公司的负责人,是一名软件架构和开发顾问。 文章要点 虽然开源开发不会消失,但商业开源厂商的未来不是很有希望。随着全面管理的...

linuxCool
25分钟前
1
0
OSChina 周三乱弹 —— 谈什么对象?睡什么觉?

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @胖达panda :最肯忘却古人诗,最不屑一顾是相思。分享童丽的单曲《红豆生南国》: 《红豆生南国》- 童丽 手机党少年们想听歌,请使劲儿戳(这...

小小编辑
30分钟前
81
5
stylus

stylus基础教程,stylus实例教程,stylus语法总结

miaojiangmin
今天
3
0
PHP生成CSV之内部换行

当我们使用PHP将采集到的文件内容保存到csv文件时,往往需要将采集内容进行二次过滤处理才能得到需要的内容。比如网页中的换行符,空格符等等。 对于空格等处理起来都比较简单,这里我们单独...

豆花饭烧土豆
今天
2
0
使用 mjml 生成 thymeleaf 邮件框架模板

发邮件算是系统开发的一个基本需求了,不过搞邮件模板实在是件恶心事,估计搞过的同仁都有体会。 得支持多种客户端 支持响应式 疼彻心扉的 outlook 多数客户端只支持 inline 形式的 css 布局...

郁也风
今天
8
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部