下面是Collection集合的说明:
Collection是最基本的集合接口,一个Collection代表一组Object,即Collection元素。一些Collection允许存储相同的元素而一些则不可以;一些能排序而一些不能。Jdk不提供直接继承自Collection接口的类,只提供List和Set两个子接口。
所有实现Collection接口的的类都必须提供两个标准的构造函数:一个无参的构造函数,用于创建一个空的Collection;一个有参的构造函数,用于复制一个Collection。
关于如何遍历Collection集合元素:
不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个迭代子,利用该迭代子即可逐一访问该Collection中的每一个元素。常用的做法如下:
Iterator
while(it.hashNext()){
Object
}
下面重点说说Collection接口派生的List和Set两个接口:
List接口是有序的Collection,使用此接口能够精确的控制每一个元素的插入位置。用户能够使用索引来获取元素,这一点类似于Array数组。List和Set不同的一点在于List允许有相同的元素,而Set不允许。
处理具有Collection接口必备的iterator()方法外,List还提供一个listIterator()方法,返回一个ListIterator接口,和标准的Iterator接口相比,ListIterator多了一些add()之类的方法,允许添加,删除,设定元素,还能向前或向后遍历。实现List接口的常用类有LinkedList、ArrayList、Vector,Stack是继承了Vector的类。
一下是List的几个常用子类的介绍:
LinkedList类:
LinkedList实现了List接口,它允许null元素。还有LinkedList提供额外的get,remove,insert方法在LinkedList的首部或尾部。这些操作使方法使得LinkedList可以被用作堆栈、队列、双向队列。使用LinkedList时需要注意的是:LinkedList是非同步的,如果多线程同时访问同一个LinkedList,必须自己实现访问同步。这里给出一个简单的解决方法是在创建List时构造一个同步的List,具体代码如下(参考):
List
ArrayList类:
ArrayList也继承List接口,ArrayList实现了可变大小的数组。它允许所有元素,包括null。每个ArrayList实例都有一个容量,即用于存储元素的数组的大小。这个容量可随着不断添加新元素而自动增加,但是增长算法并没有定义。当需要插入大量元素时,可在插入前调用ensureCapacity方法来增加ArrayList的容量以提高插入速率。和LinkedList一样,ArrayList也是非同步的,如果需要同步就用:
List
Vector类:
Vector非常类似ArrayList,但是Vector是同步的,由Vector创建的Iterator和ArrayList创建Iterator是同一个接口,但是由于Vector是同步的,当一个Iterator被创建而且正在被使用,而另一个线程改变了Vector的状态(比如:向Vector添加一个元素),这时候调用Iterator的方法将抛出ConcurrentModificationEx
Stack类:
Stack继承Vector而不是List,实现了一个先进后出的堆栈。Stack提供了5个额外的方法使得Vector得以被当做堆栈来使用。基本的push元素进栈和pop栈方法,还有peek方法取得栈顶元素,empty方法判断堆栈是否为空,search方法用于寻找某元素在堆栈中的位置。Stack创建后是空栈。
以下是Set接口的介绍:
Set是一种不包含重复元素的Collection,即任意的两个元素e1和e2都有如下结果
e1.equals(e2)=false,
以下是Map接口说明:
这里要特别注明的是Map并没有继承Collection接口,Map提供key到value的映射。一个Map中的key是不能相同的,每个key只能对应一个value。Map接口提供三种集合视图。Map内容可以被当做一组key-value映射。实现Map接口的类有HashTable、HashMap、WeakHashMap。
HashTable类:
HashTable实现了Map接口,实现一个key-value映射的哈希表,任何非空的对象都可以作为key或者value。添加数据使用put(key,value),取出数据使用get(key),这两个操作的时间开销均为常数。Hashtable通过initial
HashMap类:
基于哈希表的
此实现假定哈希函数将元素正确分布在各桶之间,可为基本操作(get
HashMap
通常,默认加载因子
如果很多映射关系要存储在
注意,此实现不是同步的。如果多个线程同时访问此映射,而其中至少一个线程从结构上修改了该映射,则它必须
由所有此类的“集合视图方法”所返回的迭代器都是快速失败
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出
WeakHashMap类:
以弱键 实现的基于哈希表的 Map。在 WeakHashMap 中,当某个键不再正常使用时,将自动移除其条目。更精确地说,对于一个给定的键,其映射的存在并不阻止垃圾回收器对该键的丢弃,这就使该键成为可终止的,被终止,然后被回收。丢弃某个键时,其条目从映射中有效地移除,因此,该类的行为与其他的 Map 实现有所不同。
null 值和 null 键都被支持。该类具有与 HashMap 类相似的性能特征,并具有相同的效能参数初始容量 和加载因子。
像大多数集合类一样,该类是不同步的。可以使用 Collections.synchronizedMap 方法来构造同步的 WeakHashMap。
该类主要与这样的键对象一起使用,其 equals 方法使用 == 运算符来测试对象标识。一旦这种键被丢弃,就永远无法再创建了,所以,过段时间后在 WeakHashMap 中查找此键是不可能的,不必对其项已移除而感到惊讶。该类十分适合与 equals 方法不是基于对象标识的键对象一起使用,比如,String 实例。然而,对于这种可重新创建的键对象,键若丢弃,就自动移除 WeakHashMap 条目,这种表现令人疑惑。
WeakHashMap 类的行为部分取决于垃圾回收器的动作,所以,几个常见的(虽然不是必需的)Map 常量不支持此类。因为垃圾回收器在任何时候都可能丢弃键,WeakHashMap 就像是一个被悄悄移除条目的未知线程。特别地,即使对 WeakHashMap 实例进行同步,并且没有调用任何赋值方法,在一段时间后 size 方法也可能返回较小的值,对于 isEmpty 方法,返回 false,然后返回 true,对于给定的键,containsKey 方法返回 true 然后返回 false,对于给定的键,get 方法返回一个值,但接着返回 null,对于以前出现在映射中的键,put 方法返回 null,而 remove 方法返回 false,对于键集、值集、项集进行的检查,生成的元素数量越来越少。
WeakHashMap 中的每个键对象间接地存储为一个弱引用的指示对象。因此,不管是在映射内还是在映射之外,只有在垃圾回收器清除某个键的弱引用之后,该键才会自动移除。
实现注意事项:WeakHashMap 中的值对象由普通的强引用保持。因此应该小心谨慎,确保值对象不会直接或间接地强引用其自身的键,因为这会阻止键的丢弃。注意,值对象可以通过 WeakHashMap 本身间接引用其对应的键;这就是说,某个值对象可能强引用某个其他的键对象,而与该键对象相关联的值对象转而强引用第一个值对象的键。处理此问题的一种方法是,在插入前将值自身包装在 WeakReferences 中,如:m.put(key, new WeakReference(value)),然后,分别用 get 进行解包。
该类所有“collection 视图方法”返回的迭代器均是快速失败的:在迭代器创建之后,如果从结构上对映射进行修改,除非通过迭代器自身的 remove 或 add 方法,其他任何时间任何方式的修改,迭代器都将抛出 ConcurrentModificationEx
注意,迭代器的快速失败行为不能得到保证,一般来说,存在不同步的并发修改时,不可能作出任何坚决的保证。快速失败迭代器尽最大努力抛出 ConcurrentModificationEx
最后简单总结:
ArrayList是基于动态数组的,LinkedList是基于链表的;因此查询和修改较快的是ArrayList,插入和删除较快的是LinkedList。因为ArrayList插入或删除操作时需要移动元素,而LinkedList查询修改时需要移动指针。
ArrayList和Vector都是基于动态数组的,如果插入的元素超出了原有的容量,ArrayList和Vector都会自动增加容量,但是ArrayList默认增加原来的50%,而Vector默认增加原来的一倍也就是100%,因此如果要在集合中保存大量的数据,则使用Vector。还有就是Vector是线程同步安全的。而ArrayList是非同步的,线程不安全的,因此,在单线程下用ArrayList比较好,在多线程的条件下,用Vector性能较好。