List 接口以及实现类和相关类源码分析

List 接口以及实现类和相关类源码分析


List接口分析

接口描述

用户可以对列表进行随机的读取(get),插入(add),删除(remove),修改(set),也可批量增加(addAll),删除(removeAll,retainAll),获取(subList)。
还有一些判定操作:包含(contains[All]),相等(equals),索引(indexOf,lastIndexOf),大小(size)。
还有获取元素类型数组的操作:toArray()

注意事项

两种迭代器IteratorListIterator:
Iterator 正向遍历列表元素的迭代器
ListIterator 支持正向和反向列表元素的迭代器,也支持插入和删除元素,也能从列表中指定位置开始的列表迭代器
插入和删除元素
List接口的不同实现,在插入和删除上开销不一样,在使用具体实现的时候注意区分。
元素限制
某些实现可能包含的元素有限制,某些实现禁止null元素,某些查询不合格的元素是否存在可能会抛出异常,而某些可能返回false

ArrayList源码分析

类描述

随机访问列表,可clone,可序列化,允许元素为null在内的所有元素,非同步类(非线程安全)。
访问元素是O(1)时间,添加元素是O(n)时间。 size <= capacity。

注意事项

  • 此实现是非同步的
    如果多线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改 了列表,那么它必须保持同步。一般是使用自然封装该列表的对象进行同步操作来完成。或者使用Collections.synchronizedList()方法来获取该实现的同步视图,最好在创建时完成,以防意外对列表进行不同步的访问。
  • 迭代器
    该实现返回的iteratorlistIterator快速失败的:再创建迭代器之后,除非通过迭代器自身的removeadd方法从结构上对列表进行修改,否则在任何时间以任何形式对列表进行修改,迭代器都会抛出ConcurrentModificationException。因此面对并发的修改,迭代器很快就会完全失败。

结构上的修改:指的是添加或删除一个或多个元素;显式调整底层数组的大小;仅仅设置元素的值不是结构上的修改。
快速失败无法得到保证,一般来说,该行为仅用于检测bug。快速失败迭代器会 尽最大可能抛出ConcurrentModificationException,因此,为提高此类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法。

  • 从源码看迭代器快速失败行为
    ArrayList类中有modCount属性来记录对象修改的次数,迭代器内部类Itr中有expectedModCount属性,该属性初始化为外部类的modCount,客户端调用ArrayList对象的iterator()方法时,ArrayList新建一个Itr实例返回。
    每调用一次外部类中的所有修改内部数组结构的方法,modCount属性加1,这样在多线程环境下,一个线程修改了内部数组的结构,另一个线程使用迭代器遍历数组,将会产生expectedModCountmodCount不一致的情况,因此会抛出ConcurrentModificationException异常。
    而通过迭代器 修改内部数组结构,则不会抛出异常,为什么呢?迭代器也是通过调用外部类的方法来移除数组中的某个元素,在移除元素后,迭代器在方法中将expectedModCount更新为modCount
  • 一些源码中学到的其他东西
    1. 每次扩充容量都是扩充原来容量的1.5倍。(源码对边界越界情况检查的非常严格,值得学习)
    2. 删除元素(批量删除,个体删除,全部删除),删除完之后将引用设置为null,方便GC回收垃圾。
    3. 序列化和反序列化,先将size序列化,再逐个序列化元素。反序列化也一样,先反序列化size,再逐个反序列化元素。

LinkedList源码分析

类描述

接口ListDeque的实现类,可clone,可序列化,允许null元素,除了List接口之外,该实现类还在列表的开头和结尾获取,删除,插入元素提供了统一的命名方法,允许这些操作将列表作为堆栈队列双端队列使用。
在结尾插入元素的操作:
add(e)addAll(Collection)addLast(E)boolean offer(E)boolean offerLast(E)
其他操作参见JDK文档。一定不要想当然的认为push或pop等操作就是在结尾操作元素的,在使用过程中一定要仔细查阅API
该实现类也不是同步的,多线程修改也会造成对象状态不一致的情景,同样可以使用Collections.synchronizedList()方法得到同步视图
迭代器也是
快速失败
的,对结构上的修改,除非通过迭代器自身的修改,其他任何时间任何方式的修改,迭代器都将抛出ConcurrentModificationException异常。

注意事项

ArrayList注意事项类似,可以参考ArrayList的注意事项。
为什么LinkedList类实现了Deque接口,而ArrayList类却没有呢?
LinkedList类内部实现是链表形式,对链表的插入、删除时间复杂度都是O(1),并且,队列、双端队列和堆栈的操作大部分都是在链表的头部和结尾,插入删除非常方便。 而ArrayList类的内部实现是数组,数组是随机访问速度比较快,但是在头部的插入和删除需要挪动整个数组(或者得时刻记录这头部下标,这样造成的复杂程度和联动反应“比较大”),代价略大。

List同步类(同步视图)

在上面两个实现类中我们可以看到,它们都是非同步的,所以在多线程环境下是不能使用的(只读必须可以啊),特别是多线程中有修改列表结构的线程,那么出错的概率将会很大。
于是Collections类提供了synchronizedList()静态方法来讲非同步的List实现类包装成同步类(我更习惯称之为同步视图)。
说到这里不得不提一个类Collections

Collections类描述

该类完全由在Collection上进行操作或返回Collection的静态方法组成。它包含在Collection上操作的多态算法(排序、查找等)
如果为此类的方法提供的Collection或类对象为null的话,这些方法将抛出NullPointerException
该类内部提供了几种包装器类,例如:不可修改的xxx,同步的xxx,检查类型的xxx(其中xxx为Collection下的接口或实现类)。

针对List的同步视图、不可修改视图和检查类型视图通过源码进行分析

  • SynchronizedListSynchronizedRandomAccessList
    着重分析SynchronizedList,后者是继承了前者,在subList操作上不一样(前者的subList操作返回的子列表需要包装为SynchronizedList而后者需要包装为SynchronizedRandomAccessList)。
    SynchronizedList类其实是List实现类的同步视图,将实现类组合到自身,并且自身包含一个对象锁,每次调用List接口的某个操作,都会锁定整个方法,然后将请求委托给实现类,以此达到同步的目的。

题外话:同步视图是对整个方法进行加锁,串化执行,这样的效率显然不是满足高并发的需求,多线程同时竞争一个锁,这和单线程有什么区别。

  • UnmodifiableListUnmodifiableRandomAccessList
    此两个内部类是List实现类的不能修改类视图(无论是修改结构还是元素值),调用修改对象的方法将抛出UnsupportedOperationException异常。
  • CheckedListCheckedRandomAccessList
    这两个内部类是List实现类的检查类型视图,构造该内部类的时候,需要传递给构造方法元素类型信息,每个读取方法都返回和类型匹配的元素,每个设置方法都先检查类型是否匹配。

时间: 2024-10-10 15:18:30

List 接口以及实现类和相关类源码分析的相关文章

Cocos2dx-3.x 中CCCamera相机类详解及源码分析

Cocos2d-x 3.3版本中加入了相机这个类,该类在3D游戏中是必不可少的,在3D立体游戏中,往往需要视野角度的变化,通过相机的变换才能观察和体验整个游戏世界. CCCamera类基本使用 在游戏中一般有两种类型的相机:一种是透视相机,它在3D游戏中十分常见:另一种是正交相机,它没有透视相机的近大远小的效果而是相机内任何位置的物体大小比例都是一样的. 上图是透视相机的原理图,一般来说,我们通过以下代码创建: _camera = Camera::createPerspective(60, (G

7.Java集合-Arrays类实现原理及源码分析

Java集合---Arrays类源码解析 转自:http://www.cnblogs.com/ITtangtang/p/3948765.html 一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类型:采用改进的归并排序. 1.对于基本类型源码分析如下(以int[]为例): Java对Primitive(int,float等原型数据)数组采用快速排序,对

Cordova Android源码分析系列二(CordovaWebView相关类分析)

本篇文章是Cordova Android源码分析系列文章的第二篇,主要分析CordovaWebView和CordovaWebViewClient类,通过分析代码可以知道Web网页加载的过程,错误出来,多线程处理等. CordovaWebView类分析 CordovaWebView类继承了Android WebView类,这是一个很自然的实现,共1000多行代码.包含了PluginManager pluginManager,BroadcastReceiver receiver,CordovaInt

AppWidget源码分析---接口类

最近项目中接触到AppWidget,相对来说这部分比较简单,所以趁着空余时间详细阅读了AppWidget的源码.这篇文章主要是从源码上分析AppWidget中API类的相关原理,相关类的简单功能介绍和实现原理.关于使用,建议看指导文档. 简述 AppWidget相关的API类(供我们应用开发者使用的类)主要有: AppWidgetProvider:继承这个类,来提供Appwidget. AppWidgetManager:提供了AppWidget的管理接口,比如更新,绑定AppWidget id,

Orchard源码分析(5):Host相关(Orchard.Environment.DefaultOrchardHost类)

概述 Host 是应用程序域级的单例,代表了Orchard应用程序.其处理应用程序生命周期中的初始化.BeginRequest事件.EndRequest事件等. 可以简单理解为HttpApplication的功能转移到了Host身上.从源码角度上看,Host对应的是实现了IOrchardHost接口的 DefaultOrchardHost类. 回顾一下之前对Orchard.Web.MvcApplication类的分析.在Orchard启动时,会创建一个DefaultOrchardHost对象:

Queue(队列)接口和其实现类PriorityQueue(优先级队列)源码解析

前面介绍的Stack是新进后出,而Queue是先进先出的 1.Queue结构 public interface Queue<E> extends Collection<E> { boolean add(E e); boolean offer(E e); E remove(); E poll(); E element(); E peek(); } Queue是一个接口. 2.PriorityQueue源码分析 PriorityQueue是一个优先队列,和先进先出的队列的区别是: 优先

CloudStack核心类ApiServlet、ApiServer、ApiDispatcher、GenericDaoBase源码分析

ApiServlet 首先从整体上看下ApiServlet,Outline视图如下, 一.注意@Inject依赖的是javax.inject.jar,它和spring的@Autowired的区别在于使用它时变量不用生成相应的set方法. 二.CloudStack所有的请求都会被ApiSerlet拦截处理,进入到doGet()或者doPost()方法,然后统一交由processRequest()处理. 三.processRequestInContext()方法: 1.更多的是日志记录和异常信息处理

Spring源码分析——BeanFactory体系之抽象类、类分析(二)

上一篇分析了BeanFactory体系的2个类,SimpleAliasRegistry和DefaultSingletonBeanRegistry——Spring源码分析——BeanFactory体系之抽象类.类分析(一),今天继续分析. 一.工厂Bean注册支持——FactoryBeanRegistrySupport 废话不多说,直接看我注释的源码: /* * Copyright 2002-2012 the original author or authors. * * Licensed und

Struts2 源码分析——Result类实例

本章简言 上一章笔者讲到关于DefaultActionInvocation类执行action的相关知识.我们清楚的知道在执行action类实例之后会相关处理返回的结果.而这章笔者将对处理结果相关的内容进行讲解.笔者叫他们为Result类实例.如果还记得在上一章最后笔者说可以把处理action执行的结果简单的理解处理网页.而且还用红色标识.实际是处理跟表现层有关的内容.而不是页面上的内容.如HTML.即是MVC里面的C到V的内容.当然这还关系到配置文件里面的result元素节点信息.如strtus