Java总结 - List实现类ArrayList&LinkedList

markdown_img_paste_2019012411263659

上面基本就是List集合类的类图关系了,图中省略掉了比如Cloneable等标记接口,那么List分别具体的主要实现类有:ArrayList,Vector,LinkedList,Stack,那么这篇文章会对这四个实现类进行介绍(由于篇幅原因,本文只说到了ArrayList和LinkedList)

ArrayList

这是最常用的List的实现类,那么这个类的存储是由数组实现的,如果超过数组规定阀值,那么就会进行自动扩容,自动扩容其实就是将数组数据复制到一个新的更大的数组中以达到扩容的目的,我们来看一下ArrayList的部分属性源码

//默认容量,将在添加第一个元素时扩展为 DEFAULT_CAPACITY private static final int DEFAULT_CAPACITY = 10; //共享空数组实例 private static final Object[] EMPTY_ELEMENTDATA = {}; //这是保存数据的数组,非私有以简化嵌套类访问 //arraylist 的容量是此array数组的长度 //当第一个元素被添加时,当任何一个空ArrayList的elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA都会被扩展为DEFAULT_CAPACITY transient Object[] elementData; //共享空数组实例,用于默认大小的空实例 //将其与 EMPTY_ELEMENTDATA 区分开来,以了解添加第一个元素时要增加多少 private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; private int size; ...

初始化

ArrayList提供了三种构造方法,如下

public ArrayList() {...} public ArrayList(int initialCapacity) {...} public ArrayList(Collection<? extends E> c) {...}

空参 : 我们从第一个ArrayList的空参的构造方法介绍,下面是源码的实现

public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; }

怎么理解之前的代码注释当第一个元素被添加时,任何一个空ArrayList的elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA都会被扩展为DEFAULT_CAPACITY呢?ArrayList为空并且两个属性值相等的时候,说明是调用了无参构造,在构造执行完的时候,并没有被构造为默认大小,而是当第一个元素添加时候,判断的条件成立即两属性值相等,才会进行扩展为默认大小

所以说当我们构建空参对象的时候,初始值数组长度是为0的,并没有直接扩充为长度为10的数组,代码验证

public static void main(String[] args) throws Exception { ArrayList<String> arrayList = new ArrayList<>(); getSize(arrayList); arrayList.add("x"); getSize(arrayList); } private static void getSize(ArrayList<String> arrayList) throws Exception { Field elementData = arrayList.getClass().getDeclaredField("elementData"); elementData.setAccessible(true); Object[] o = (Object[]) elementData.get(arrayList); System.out.println(o.length); } //0 10 //而当我们以0为初始化长度参数创建ArrayList的时候,其实就是告诉他我一个都不存,所以他就创建了一个0长度的数组,而当我们添加数据的时候,就会自动扩容一个 //验证 : 可以将初始化改成这样 ArrayList<String> arrayList = new ArrayList<>(0); //然后输出为 0 1 //所以这也就是为什么要区分DEFAULTCAPACITY_EMPTY_ELEMENTDATA 与 EMPTY_ELEMENTDATA

从中我们可以看到,只是初始化空参的ArrayList的话,那么只是将一个空数组赋值给elementData属性,那么EMPTY_ELEMENTDATA也是空数组对象,他是用来干啥的呢?他只是用作是构造有参空ArrayLIst的时候=0.而DEFAULTCAPACITY_EMPTY_ELEMENTDATA才是我们构造空参ArrayList时候使用的对象,即这样的,从下面一个分析另一个构造的时候就能看出来

//使用EMPTY_ELEMENTDATA List<String> arrayList = new ArrayList<>(0); //使用DEFAULTCAPACITY_EMPTY_ELEMENTDATA List<String> arrayList = new ArrayList<>();

我们还注意到DEFAULTCAPACITY_EMPTY_ELEMENTDATA与EMPTY_ELEMENTDATA都是以private static final修饰,所以这两个空数组是属于类的,仅存在一份,说这个的意思就是,当你创建两个容量为0的ArrayList的时候,都会指向一个堆内存中的对象,我们可以尝试一下

public static void main(String[] args) throws Exception { ArrayList<String> list1 = new ArrayList<>(); Field elementData1 = list1.getClass().getDeclaredField("elementData"); elementData1.setAccessible(true); Object o1 = elementData1.get(list1); ArrayList<String> list2 = new ArrayList<>(); Field elementData2 = list2.getClass().getDeclaredField("elementData"); elementData2.setAccessible(true); Object o2 = elementData1.get(list2); System.out.println(o1 == o2); } //true

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zwsjsd.html