欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Java开发使用ArrayList深度解析

程序员文章站 2022-03-26 18:17:46
ArrayList 底层学习底层知识底层使用的是数组的数据结构属性//默认的初始化容量private static final int DEFAULT_CAPACITY = 10;//一个空的Object数组的实例(当使用有参构造器public ArrayList(int initialCapacity)时候自定义容量为0时候赋值给elementData)private static final Object[] EMPTY_ELEMENTDATA = {};//和上面一样是个空数组实例(当...

ArrayList 底层学习

底层知识

底层使用的是数组的数据结构

属性

//默认的初始化容量 private static final int DEFAULT_CAPACITY = 10; //一个空的Object数组的实例(当使用有参构造器public ArrayList(int initialCapacity)时候自定义容量为0时候赋值给elementData) private static final Object[] EMPTY_ELEMENTDATA = {}; //和上面一样是个空数组实例(当使用默认无参构造器时赋值给elementData) private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //真正的存放数组的数组 transient Object[] elementData; //数组的长度 private int size; 

构造器

 public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity];//如果>0则直接立马给数组分配空间 } else if (initialCapacity == 0) { //如果输入参数为0,那么就赋值一个空数组 this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } public ArrayList() { //可在属性中查看 this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } 

从这两个构造器中我们发现,如果我们给它一个整型参数且>0,那么会立马给elementData数组分配空间,如果为0则不管。但是如果调用无参构造器的时候我们发现他并没有分配空间,而是将它指向默认的空的elementData对象,但是并没有立马给他分配空间

newCapacity(int minCapacity)

//这个是将数组进行一个扩容操作, private int newCapacity(int minCapacity) { //保存旧数组的容量 int oldCapacity = elementData.length; //新数组的大小为旧数组+旧数组右移一位的和,相当于是扩大为原来1.5倍(newCapacity为扩容后的容量) int newCapacity = oldCapacity + (oldCapacity >> 1); //下面判断为真的例子 /*
    	当我们使用默认构造器时候,我们的elementData对象是一个空数组,
    	那么oldCapacity = elementData.length = 0
    	那么 newCapacity = oldCapacity + (oldCapacity >> 1) = 0
    	minCapacity = size + 1 ,此时size = 0,minCapacity = 1 
    	newCapacity - minCapacity = -1 <= 0
    	*/ if (newCapacity - minCapacity <= 0) { //进入下面的判断分支说明使用的是默认构造器 if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) return Math.max(DEFAULT_CAPACITY, minCapacity); // overflow(内存溢出) if (minCapacity < 0) throw new OutOfMemoryError(); //如果使用有参构造器并且自定义capacity定义为0,就会使用下面的return,即返回1 //(非常不建议这样,因为这样会导致数组不停的扩容,影响性能) return minCapacity; } //这是正常的扩容容量, return (newCapacity - MAX_ARRAY_SIZE <= 0) //判断新容量不超过最大容量的三目运算 ? newCapacity //为真 : hugeCapacity(minCapacity); //为假(分析可以看下面) } private static int hugeCapacity(int minCapacity) { //内存已经用完了 if (minCapacity < 0) throw new OutOfMemoryError(); //minCapacity已经超过定义的最大数组长度的三目运算 return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE //为真(设置为最大的Int的最大数值容量) : MAX_ARRAY_SIZE; //为假(设置为定义的最大容量) } 

add()方法

 //这个是扩容时调用的grow方法 private Object[] grow(int minCapacity) { return elementData = Arrays.copyOf(elementData,//这里是将旧数组的信息复制到新数组中 newCapacity(minCapacity)); } private Object[] grow() { return grow(size + 1); } private void add(E e, Object[] elementData, int s) { //这里的s传入的基本都是size //当size的长度达到了数组的定义的长度时候就需要会进行扩容 if (s == elementData.length) elementData = grow(); //这里将数据保存进数组中,并且将size + 1  elementData[s] = e; size = s + 1; } //平时调用的最多的方法 public boolean add(E e) { //这个就是继续数组被更改的次数 modCount++; //调用私有方法add Object[] elementData; if ((s = size) == (elementData = this.elementData).length) elementData = grow(); System.arraycopy(elementData, index, elementData, index + 1, s - index); elementData[index] = element; size = s + 1; } //-----------------------------下面为按下标进行一个插入操作--------------------------------------------- private void rangeCheckForAdd(int index) { if (index > size || index < 0) throw new IndexOutOfBoundsException(outOfBoundsMsg(index)); } /*
	这个方法我们可以明确的发现
	说明:只能插入在list的size以内的数据,相当于只能替换时候使用该方法,平时的插入还是以add(E e)为主
	*/ public void add(int index, E element) { //对该下标进行一个判断,看看是否超过size或者index < 0  rangeCheckForAdd(index); //对数组修改操作 + 1 modCount++; final int s; Object[] elementData; //和一个参数的add()方法一样,判断需不需要进行一个扩容操作 if ((s = size) == (elementData = this.elementData).length) elementData = grow(); System.arraycopy(elementData, index, elementData, index + 1, s - index); //将数据存储到数组中 elementData[index] = element; //size + 1 size = s + 1; } 

Vector(线程安全)

底层也是使用的暴力加锁方法,直接使用synchronized修饰

如何选择线程安全的集合

1.可以选择线程安全的类,例如Vector,HashTable,ConcurrentHashMap

2.可以使用Collections.synchronized*(),这样的方法

本文地址:https://blog.csdn.net/fxhhh123/article/details/108032853

相关标签: java arraylist