Java容器Collection├List 接口│├LinkedList 链表│├ArrayList 顺序结构动态数组类│└Vector 向量│ └Stack 栈└Set Map├Hashtable├HashMap└WeakHashMap首先介绍Collection接口
Collection是最基本的集合接口一个Collection代表一组Object即Collection的元素(Elements)
Java SDK不提供直接继承自Collection的类Java SDK提供的类都是继承自Collection的子接口如List和Set
所有实现Collection接口的类都必须提供两个标准的构造函数无参数的构造函数用于创建一个空的Collection有一个Collection参数的构造函数用于创建一个新的Collection这个新的Collection与传入的Collection有相同的元素后一个构造函数允许用户复制一个Collection
List是有序的Collection使用此接口能够精确的控制每个元素插入的位置用户能够使用索引(元素在List中的位置类似于数组下标)来访问List中的元素这类似于Java的数组
对应list的用法分为对数据进行操作(增删改查)对数据存储后遍历显示这两大类应用
数据定位List接口提供了两种搜索指定对象的方法从性能的观点来看应该小心使用这些方法
为了提高效率通常我们对list中元素排好序进行折半查找通过获取子列表缩小查找范围子列表的获取实现时注意列表中存在重复元素对获取边界值的影响
对于元素对象需要重写equals(Object o)和hashCode()方法 实现自定义的对象相等在比较元素相等时我们应先判断元素的hashCode值是否相等对于判断列表是否相等(元素的值和元素的顺序)也可以使用列表的hashCode方法来提高判读的效率
利用Collections也可以实现对list元素进行排序及其查找列表中的所有元素都必须实现Comparable接口 对于支持范型的jdk版本来说<T> T[] toArray(T[] a)
返回按适当顺序(从第一个元素到最后一个元素)包含列表中所有元素的数组返回数组的运行时类型是指定数组的运行时类型
indexOf(Object o)
返回此列表中第一次出现的指定元素的索引如果此列表不包含该元素则返回
lastIndexOf(Object o)
返回此列表中最后出现的指定元素的索引如果列表不包含此元素则返回
get(int index)
返回列表中指定位置的元素
List<E> subList(int fromIndex int toIndex)
返回列表中指定的 fromIndex(包括 )和 toIndex(不包括)之间的部分视图
inthashCode()
返回列表的哈希码值列表的哈希码定义为以下计算的结果int hashCode = Iterator<E> i = erator()while (ihasNext()) { E obj = inext()hashCode = *hashCode + (obj==null ? objhashCode())}
这确保了 listequals(list)意味着对于任何两个列表 list 和 list 而言可实现 listhashCode()==listhashCode()正如 ObjecthashCode() 的常规协定所要求的
增boolean add(E e)
向列表的尾部添加指定的元素(可选操作)
void add(int indexE element)
在列表的指定位置插入指定元素(可选操作)
删删除单个一组全部元素
E remove(int index)
移除列表中指定位置的元素(可选操作)
boolean remove(Object o)
从此列表中移除第一次出现的指定元素(如果存在)(可选操作)
boolean removeAll(Collection<?> c)
从列表中移除指定 collection中包含的其所有元素(可选操作)
boolean retainAll(Collection<?> c)
仅在列表中保留指定 collection中所包含的元素(可选操作)
void clear()
从列表中移除所有元素(可选操作)
改E set(int indexE element)
用指定元素替换列表中指定位置的元素(可选操作)
遍历iterator()和ListIterator的差别?
Iterator<E> iterator()
返回按适当顺序在列表的元素上进行迭代的迭代器
ListIterator<E> listIterator()
返回此列表元素的列表迭代器(按适当顺序)
ListIterator<E> listIterator(int index)
返回列表中元素的列表迭代器(按适当顺序)从列表的指定位置开始
Object[] toArray()
返回按适当顺序包含列表中的所有元素的数组(从第一个元素到最后一个元素)
<T> T[] toArray(T[] a)
返回按适当顺序(从第一个元素到最后一个元素)包含列表中所有元素的数组返回数组的运行时类型是指定数组的运行时类型
针对list接口的实现类LinkedList ArrayListVectorStack各自都增加了那些方法实际使用时如何选择?
首先来看List接口的链接列表实现LinkedList所有已实现的接口SerializableCloneable Iterable<E> Collection<E> Deque<E> List<E> Queue<E>实现所有可选的列表操作并且允许所有元素(包括null)除了实现 List接口外LinkedList 类还为在列表的开头及结尾 getremove和 insert 元素提供了统一的命名方法这些操作允许将链接列表用作堆栈队列或双端队列
此类实现 Deque接口为 addpoll提供先进先出队列操作以及其他堆栈和双端队列操作
再来看List接口的数组列表实现 ArrayList所有已实现的接口SerializableCloneable Iterable<E> Collection<E> List<E> RandomAccess List接口的大小可变数组的实现实现了所有可选列表操作并允许包括 null在内的所有元素除了实现 List 接口外此类还提供一些方法来操作内部用来存储列表的数组的大小(此类大致上等同于 Vector类除了此类是不同步的)
sizeisEmptygetsetiterator和 listIterator 操作都以固定时间运行add 操作以分摊的固定时间 运行也就是说添加 n个元素需要 O(n) 时间其他所有操作都以线性时间运行(大体上讲)与用于 LinkedList实现的常数因子相比此实现的常数因子较低
每个 ArrayList实例都有一个容量该容量是指用来存储列表元素的数组的大小它总是至少等于列表的大小随着向 ArrayList中不断添加元素其容量也自动增长并未指定增长策略的细节因为这不只是添加元素会带来分摊固定时间开销那样简单
在添加大量元素前应用程序可以使用 ensureCapacity操作来增加 ArrayList 实例的容量这可以减少递增式再分配的数量
关于arrayList的容量和元素个数trimToSize()
将此 ArrayList实例的容量调整为列表的当前大小
int size()
返回此列表中的元素数
void ensureCapacity(int minCapacity)
如有必要增加此 ArrayList 实例的容量以确保它至少能够容纳最小容量参数所指定的元素数
总结 对于频繁使用插入与删除操作使用linkedlist是个不错的选择对于经常进行索引操作则arrylist较好从元素个数来判断对于知道元素个数用来遍历显示时我们用arrayList更高效对于将列表用作堆栈队列或双端队列操作时选择linkedlist实际应用从数据库返回结果集显示在页面时arrayList更合适
Linkedlistarrylist此实现不是同步的如果多个线程同时访问一个ArrayList或链接列表实例而其中至少一个线程从结构上修改了列表那么它必须保持外部同步(结构上的修改是指任何添加或删除一个或多个元素的操作或者显式调整底层数组的大小仅仅设置元素的值不是结构上的修改)这一般通过对自然封装该列表的对象进行同步操作来完成如果不存在这样的对象则应该使用CollectionssynchronizedList方法将该列表包装起来这最好在创建时完成以防止意外对列表进行不同步的访问List list = CollectionssynchronizedList(new ArrayList(……))List list = CollectionssynchronizedList(new LinkedList(……))vector的Vector中的所有方法前面都有一个synchronized关键字做修饰是线程安全的
Linkedlistarrylistvector类的iterator 和 listIterator方法返回的迭代器是快速失败的在创建迭代器之后除非通过迭代器自身的 remove或 add 方法从结构上对列表进行修改否则在任何时间以任何方式对列表进行修改迭代器都会抛出ConcurrentModificationException因此面对并发的修改迭代器很快就会完全失败而不是冒着在将来某个不确定时间发生任意不确定行为的风险注意迭代器的快速失败行为无法得到保证因为一般来说不可能对是否出现不同步并发修改做出任何硬性保证快速失败迭代器会尽最大努力抛出ConcurrentModificationException因此为提高这类迭代器的正确性而编写一个依赖于此异常的程序是错误的做法迭代器的快速失败行为应该仅用于检测 bug因此实际应用是先通过iterator和 listIterator遍历数组确定元素后再进行增删时应用迭代器自身的方法来修改是否类似?个人觉得也不能在迭代器中修改如果修改重新生成迭代器