List集合了解一下

声明:我学习Java基础都会参考这位博主的文章,参考他的思路去学习,附上其博客目录导航,推荐大家去看,很不错,Java3y http://www.zhongfucheng.bitcron.com/post/shou-ji/pcduan-wen-zhang-dao-hang
另部分图片也摘自他的文章。
今天看了一眼List接口下ArrayList以及LinkedList的源码,特此记录。首先附上Java集合框图。

由结构图可以看出list接口是继承了Collection接口的(之前没注意过接口之间也是有继承关系的,以为接口只能使用implements)。今天着重看一下ArrayList和LinkedList的源码。
 
首先是ArrayList
 
1、首先看arraylist的继承关系,arraylist继承了AbstractList抽象类(AbstractList抽象类继承了AbstractCollection抽象类),实现了List接口。
2、再看类中定义的变量。盗图预警,侵删。
  1. 从定义的变量可以看出arraylist的底层是数组,默认返回的是DEFAULTCAPACITY_EMPTY_ELEMENTDATA数组,也就是说当调用new ArrayList()时,默认返回的是DEFAULTCAPACITY_EMPTY_ELEMENTDATA数组。
  2. elementData即为实际存放内容的数组,第一次向该数组中添加元素时,该数组容量会初始化为10。

 


3、再看ArrayList的构造方法,ArrayList有三个构造函数,
  1. 默认构造函数就是返回默认DEFAULTCAPACITY_EMPTY_ELEMENTDATA数组
  2. 指定容量的构造函数,那么就初始化为指定容量大小的数组
  3. 将指定的集合转化为ArrayList元素,如果指定的集合大小为0,则返回EMPTY_ELEMENTDATA

 

4、再看几个常用方法
  • add方法:可以看出有两种add的方式,一个是直接添加,一个是在指定位置添加,我们发现在两种add方法中都调用了一个ensureCapacityInternal方法,当然是选择点进去看看啦。

 

看方法名貌似是确认数组容量的,想想也是,向数组中添加元素时首先要看看这数组还能不能装得下。由代码可以看出
  1. 首先确认所需的最小容量,也就是当前数组长度+1,最小容量取当前数组容量和所需最小容量两者中的最大值。然后调用ensureExplicitCapacity方法确保数组达到最小容量。ensureExplicitCapacity方法是怎么保证的,当然要点进去啊
  2. 由ensureExplicitCapacity方法中的代码可以看出,如果最小容量小于当前数组的length,则不进行操作,如果最小容量大于当前数组的length的话就需要调用grow方法扩容了,当然还是要点进去啊
  3. 从grow中可以看出首先将数组扩容为原来的1.5倍,此时如果还小于最小容量的话,就将最小容量作为newCapacity,但是要注意比较newCapacity和hugeCapacity的大小
  4. 最后调用system.arraycopy来将原数组复制到扩容后的数组中

 

 

 

 

 

 
  • 删(remove)改(set)查(get)方法都比较简单,基本就是数组的操作,就是注意参数中如果带下标要注意判断是否越界,另外要注意修改size的值。另外删除操作中将元素设为null,以便GC回收。
  • ArrayList是非线程安全的;
  • ArrayList可以存放null值
 
然后是LinkedList
 
  1. 首先也是先看看它的继承关系,LinkedList继承了AbstractSequentialList抽象类(该抽象类继承于AbstractList),同时实现了list接口和Deque接口,其底层为一个双向链表。
  2. 再看其中的变量,定义了头结点和尾节点,其中Node为LinkedList的内部类,

 

 

 



3、然后就是构造方法了,构造方法有两个,e...没什么好说的

 

 
4、那再常用方法
  • 增(add)
似乎也没什么好说的,就是链表的插入操作,add方法在尾节点后插入新节点,注意判断当前链表是否为空,如果当前链表为空的话要将插入的节点设置为头结点。
另外作为一个双向链表,当然要提供addFirst(从前插入),addLast(从后插入)方法
  • 删(remove)
默认删除方法(remove())中调用的是removeFirst方法,删除的是头结点。
remove(int index)方法首先需要判断下标是否合法
removeFirst和removeLast方法 调用unlinkFirst和unlinkLast方法,为空则抛NoSuchElementException
pollFirst和pollLast方法 调用unlinkFirst和unlinkLast方法,为空则返回null
peekFirst和peekLast方法 只返回值,不调用unlink方法,即不删除
  • 改(set)
  • 查(get)
根据下标get时,会先判断下标是在链表前半段还是下标的后半段,然后决定是从前遍历还是从后遍历。

好吧,后边写的确实不是很走心,因为都是基本的数据结构的操作,大家一看就懂的,也可能是我没思考到位,没有发现其中的重难点。以后再补充吧。总结这个还挺费时间的,不过我相信好记性不如烂笔头啦。
posted @ 2018-08-28 14:59  朝朝暮暮dx  阅读(138)  评论(0编辑  收藏  举报