List(JDK1.7)(1)

java.util包.

与Set不同, List允许重复的元素。即 e1.equals(e2)。

部分方法定义

  • int size();

返回列表中元素的个数,如果超过Integer.MAX_VALUE,就返回Integer.MAX_VALUE

  • boolean isEmpty();
  • boolean contains(Object o);

对于目标元素o, 如果列表中至少存在一个元素e:o==null? e==null ; o.eqauls(e)。

如果目标元素不可比较,将会抛出异常:ClassCastException.

如果目标元素为null,并且该列表不允许null元素,则抛出异常:NullPointerException.

  • Iterator<E> iterator();
  • Object[] toArray();

以恰当的顺序返回列表中的所有元素。

返回的数组是安全的,因为它的引用不是由该列表维护的。也就是说,该方法必须申请一个新的数组,即使list本身就是基于数组的。因此,调用者可以自由地修改返回的数组。

该方法作为一个桥梁,建立起基于数组和基于集合的API。

  • <T> T[] toArray(T[] a);

返回数组的运行时类型是指定的数组类型。

如果列表恰好是该类型的,就会直接返回。否则,必须申请一个新数组,新数组的大小恰好就是列表的size。

如果列表是指定类型的,并且数组中还有剩余空间,则未使用的数组位置全部置null。——这一点很有用,因为可以判断列表的长度。前提是调用者知道该list不会包含任何null元素。

  • boolean add(E e);

支持该操作的List,可能会限制允许加入该list的元素。比如,有些list可能会拒绝添加null作为元素,而其他list有可能限制元素的类型。

UnsupportedOperationException, 如果该List不支持add方法。

ClassCastException, 指定元素的类class,不允许它被添加到该list中。

NullPointerException,如果指定元素是null,并且该List不允许null元素。

IllegalArgumentException,如果该元素的某些属性,不允许它被添加到该list中。

  • boolean remove(Object o);

删除第一次出现的那个元素,即下标最小的: o==null ? get(i )==null : o.eqauls(get(i );

如果列表中不包含这样的元素,就不变。

ClassCastException,如果指定元素的类型无法与list匹配。

NullPointerException, 如果指定元素是null,并且list不允许null元素。

UnsupportedOperationException,list不支持remove方法。

  • boolean containsAll(Collection<?> c);

如果列表中包含了指定collection中的所有元素,返回true。

ClassCastException,如果指定collection中的一个或多个元素的类型与该list不匹配

NullPointerException,指定collection中包含一个或多个null,而list不允许null元素。

  • boolean addAll(Collection<? extends E> c);

UnsupportedOperationException

ClassCastException

NullPointerException

IllegalArgumentException

  • boolean addAll(int index, Collection<? extends E> c);

在指定的下标处插入指定collection中的所有元素。

IndexOutOfBoundsException,如果下标超出范围。

  • boolean removeAll(Collection<?> c);

删除list中所有在c中出现的元素。

  • boolean retainAll(Collection<?> c);

保留指定集合中出现的所有元素。

NullPointerException, 如果list中包含一个null,而指定的collection是不允许null的时候。

ClassCastException

  • void clear();
  • boolean equals(Object o);

两个list相等的条件是:他们包含相同的元素,以相同的顺序。

  • int hashCode();

  • E get(int index);
  • E set(int index, E element); //替换已有下标处的元素
  • void add(int index, E element);
  • E remove(int index);
  • int indexOf(Object o);

如果存在,就返回第一次出现的下标。如果不存在,返回-1.

  • int lastIndexOf(Object o);
  • ListIterator<E> listIterator();
  • ListIterator<E> listIterator(int index); //从指定的下标开始遍历
  • List<E> subList(int fromIndex, int toIndex);

返回一个视图。包含左下标,不包含右下标。

返回的List是基于原list的,所以在返回的list中进行的非结构性修改会在原list中体现,反之亦然。

任何针对局部范围list的操作,都可以通过传递一个subList视图来代表整个list。例如,下列语句删除了list中的部分元素:

list.subList(from, to).clear();

ArrayList

List接口的一种可调整大小的基于数组的实现。实现了所有可选的list操作,也允许所有元素,包括null。

另外,该类还提供了操纵底层实现数组的大小的方法。

该类和Vector类基本是一样的,除了ArrayList是非同步的。

以常数时间运行的方法:size, isEmpty, get, set, iterator, listIterator。摊销的常数时间,即O(n ):add。粗略来说,其他方法的运行时间都是线性的。常数因子比起LinkedList要小。

每个ArrayList的实例都有一个容量capacity。这是底层数组的大小。通常,容量至少要和List的大小一样大。因为增加一个元素有常数的摊销时间,所以没有明确规定增长策略的细节。

在增加大量元素之前扩容的一个办法是使用ensureCapacity操作,这可以减少容量调整的次数。

注意ArrayList是非同步的。如果多线程同时访问同一个ArrayList实例,并且至少有一个线程修改了列表结构,就必须要有外部的同步机制。通常通过同步某些封装了该list的对象来实现,如果没有这样的对象,该list就应该使用Collections.synchronizedList()来包装。最好在创建时就这样做,可以避免对该list的意外的非同步访问。(结构性修改是指,增加或删除一个或多个元素,或者调整了底层数组的大小,只修改了元素的值不是结构性修改)。

ArrayList中的iterator()方法和listIterator()返回的迭代器都是快速失败的。如果在创建了该迭代器之后的任意时间对list进行了结构性修改,除了通过iterator本身提供的方法之外,该Iterator都会抛出一个ConcurrentModificationException异常。面对同时发生的修改,iterator会快速干脆地失败,而不是无法确定未来的冒险的、非确定性的行为。

注意,iterator提供的快速失败机制并不能保证线程安全。快速失败机制应该只用于检测bug。

AbstractList源码

抽象类实现了部分方法。

ArrayList源码细节

ArrayList继承自AbstractList抽象类。

成员变量

构造方法

get()方法

set()方法

add()方法

扩容

contains()方法

remove()方法

clear()方法

clone()方法

转换为数组

迭代器 iterator 和 listIterator

【关于Itr中的remove()方法】

注意到lastRet表示上一次读取的位置,当这个位置为-1时,remove方法抛出IllegalStateException。而这个位置 为-1的情况,一个是初始化时,还未调用过next(),另一个是在调用了remove()方法后。所以,在这两种情况下是不能调用remove()方法的,即remove()方法不能连续调用,必须和next()结合,先next()后remove()。

另外,在删除元素时,会同步更新iterator中的expectedModCount,这样保持和List中的modCount的一致,从而使得checkForComodification()检测通过,本质上并不是线程同步的,当多个Iterator同时访问同一个List时,仍然是不安全的。

【ListItr】

在Itr的基础上,增加了向前遍历的方法,相当于一个双向遍历器。还增加了set()和add()方法,使得遍历器不仅可以删除元素,还可以修改和增加元素。

特别注意的,add()方法和remove()方法都会修改lastRet值为-1,因此需要读取lastRet的方法,譬如set(),remove()都不能在这两个方法后面调用,需要先调用一次next()方法。

List的add()和remove()方法都是结构性的修改,所以迭代器中的add()和remove()方法需要同步更新modCount的值,否则会在下一次增删改查操作时,检测到不相同,而抛出ConcurrentModificationException。

子列表视图

时间: 2024-10-21 17:48:00

List(JDK1.7)(1)的相关文章

HashMap源码分析(JDK1.8)

一.HashMap简介 HashMap是一种基于数组+链表+红黑树的数据结构,其中红黑树部分在JDK1.8后引入,当链表长度大于8的时候转换为红黑树. HashMap继承于AbstractMap(Map的骨架实现类),实现Map接口. HashMap因为采用hashCode的值存储,所以性能一般情况下为O(1).   HashMap最多只允许一条记录的键为null,允许多条记录的值为null. HashMap线程不安全,如在多线程环境下可以使用Collections工具类将其转换为线程安全,也可

javase基础回顾(一)ArrayList深入解析 解读ArrayList源代码(JDK1.8.0_92)

我们在学习这一块内容时需要注意的一个问题是 集合中存放的依然是对象的引用而不是对象本身. List接口扩展了Collection并声明存储一系列元素的类集的特性.使用一个基于零的下标,元素可以通过它们在列表中的位置被插入和访问.一个列表可以包含重复元素.List在集合中是一个比较重要的知识点也是在开发中最常用的. 我们都知道ArrayList是由数组实现的,但是和数组有很大区别的是随着向ArrayList中不断添加元素,其容量也自动增长,而数组声明好之后其容量就不会改变.想要探明其中的究竟探析其

Java---20---多线程:生产者和消费者2(JDK1.5升级版)

此篇文章写的是JDK1.5升级版的生产者和消费者. Java 升级之后的解决方法: Lock java.util.concurrent.locks 接口 Lock 所有已知实现类: ReentrantLock,ReentrantReadWriteLock.ReadLock,ReentrantReadWriteLock.WriteLock public interface Lock Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作.此实现允许更灵活的结构,可

java基础知识回顾之java Thread类学习(把)--java.util.concurrent.locks(JDK1.5)与synchronized异同讲解

看API文档介绍几个方法:  JDK1.5中提供了多线程的升级解决方案: 特点: 1.将同步synchronized显示的替换成Lock                    2.接口Condition:Condition替代了Object监视器方法(wait.notify.notifyAll),分别替换成了await(),signal() (唤醒一个等待线               程),signalAll() 唤醒多个线程.一个锁可以绑定多个condition对象,可以对应好几组wait,

Java安全机制之泛型(JDK1.5)

泛型,类型安全机制. 好处: 1.将运行时期出现问题ClassCastException转移到了编译时期,方便解决问题,减少运行时期的问题,有利于程序的健壮性. 2.避免了强制转换的麻烦 泛型格式: ArrayList<String> al = new ArrayList<String>(); 若增加Integer类型的数据,在编译的时期就会提示错误. 使用迭代器取值的时候,需要声明类型 示例代码: import java.util.*; class GenericDemo2 {

【图解JDK源码】HashMap的容量大小增长原理(JDK1.6/1.7/1.8)

1. 前言 HashMap的容量大小会根据其存储数据的数量多少而自动扩充,即当HashMap存储数据的数量到达一个阈值(threshold)时,再往里面增加数据,便可能会扩充HashMap的容量. 可能? 事实上,由于JDK版本的不同,其阈值(threshold)的默认大小也变得不同(主要是计算公式的改变),甚至连判断条件也变得不一样,所以如果说threshold = capacity * loadFactor(容量 * 负载因子)将不再绝对正确,甚至说超过阈值容量就会增长也不再绝对正确,下面就

Java 环境变量配置(jdk1.8)

由于今天电脑重装系统(Win10专业版),所有的环境配置都没了,所以随手更一下这篇虽然及其简单但是又有部分和我一样的小白连配置个jdk环境都有可能会出错的(以前就有遇到过,就是根据baidu里的一些教程配置的环境变量啊,怎么还是会出现没有配置成功呢?)接下来我就和大家一起搭建一次jdk环境,大神请路过,觉得这篇教程还可以,能用上的就请收藏一下以备后用,好了废话不多说,现在开始进入正题: 准备工具:JDK8u161 开发工具:Eclipse 去oracle官网下载jdk版本,现在jdk10已经出来

使用ArrayList时代码内部发生了什么(jdk1.7)?

前言 ArrayList(这里的ArrayList是基于jdk1.7)是在项目中经常使用的集合类,例如我们从数据库中查询出一组数据.这篇文章不去剖析它的继承和实现,只是让我们知道实例化及增删改查时它的内部代码是怎么实现的. public class TestList { @Test public void testArrayList(){ List<Integer> list = new ArrayList<>(); for (int i = 0; i < 12; i++)

ArrayList集合(JDK1.8)

简述 List是继承于Collection接口,除了Collection通用的方法以外,扩展了部分只属于List的方法. 常用子类  ?ArrayList介绍 1.数据结构 其底层的数据结构是数组,数组元素类型为Object类型,即可以存放所有类型数据. 2.源码分析   2.1类的继承关系 public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Clonea

集合之HashSet(含JDK1.8源码分析)

一.前言 我们已经分析了List接口下的ArrayList和LinkedList,以及Map接口下的HashMap.LinkedHashMap.TreeMap,接下来看的是Set接口下HashSet和LinkedHashSet,其实在分析完了HashMap.LinkedHashMap之后,再来看HashSet和LinkedHashSet就会非常简单. 二.hashSet的数据结构 因为hashSet的底层是基于hashMap或linkedHashMap的(new hashSet的时候可以指定),