Collection
├List
│├LinkedList
│├ArrayList
│└Vector
│ └Stack
└Set
Map
├Hashtable
├HashMap
└WeakHashMap

Collection接口
  Collection是最基本的集合接口,一个Collection代表一lObjectQ即Collection的元素(ElementsQ。一些Collection允许相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接承自Collection的类QJava SDK提供的类都是l承自Collection的“子接口”如List和Set?BR>  所有实现Collection接口的类都必L供两个标准的构造函敎ͼ(x)无参数的构造函数用于创Z个空的CollectionQ有一个Collection参数的构造函数用于创Z个新的CollectionQ这个新的Collection与传入的Collection有相同的元素。后一个构造函数允许用户复制一个Collection?BR>  如何遍历Collection中的每一个元素?不论Collection的实际类型如何,它都支持一个iterator()的方法,该方法返回一个P代子Q用该q代子即可逐一讉KCollection中每一个元素。典型的用法如下Q?BR>    Iterator it = collection.iterator(); // 获得一个P代子
    while(it.hasNext()) {
      Object obj = it.next(); // 得到下一个元?BR>    }
  由Collection接口z的两个接口是List和Set?/FONT>

List接口
  List是有序的CollectionQ用此接口能够_的控制每个元素插入的位置。用戯够用烦(ch)引(元素在List中的位置Q类g数组下标Q来讉KList中的元素Q这cM于Java的数l?BR>和下面要提到的Set不同QList允许有相同的元素?BR>  除了hCollection接口必备的iterator()Ҏ(gu)外,Listq提供一个listIterator()Ҏ(gu)Q返回一个ListIterator接口Q和标准的Iterator接口相比QListIterator多了一些add()之类的方法,允许dQ删除,讑֮元素Q还能向前或向后遍历?BR>  实现List接口的常用类有LinkedListQArrayListQVector和Stack?/FONT>

LinkedListc?BR>  LinkedList实现了List接口Q允许null元素。此外LinkedList提供额外的getQremoveQinsertҎ(gu)在LinkedList的首部或N。这些操作LinkedList可被用作堆栈QstackQ,队列QqueueQ或双向队列QdequeQ?BR>  注意LinkedList没有同步Ҏ(gu)。如果多个线E同时访问一个ListQ则必须自己实现讉K同步。一U解x法是在创建List时构造一个同步的ListQ?BR>    List list = Collections.synchronizedList(new LinkedList(...));

ArrayListc?BR>  ArrayList实现了可变大的数组。它允许所有元素,包括null。ArrayList没有同步?BR>sizeQisEmptyQgetQsetҎ(gu)q行旉为常数。但是addҎ(gu)开销为分摊的常数Q添加n个元素需要O(n)的时间。其他的Ҏ(gu)q行旉为线性?BR>  每个ArrayList实例都有一个容量(CapacityQ,即用于存储元素的数组的大。这个容量可随着不断d新元素而自动增加,但是增长法q没有定义。当需要插入大量元素时Q在插入前可以调用ensureCapacityҎ(gu)来增加ArrayList的容量以提高插入效率?BR>  和LinkedList一PArrayList也是非同步的QunsynchronizedQ?/FONT>

Vectorc?BR>  Vector非常cMArrayListQ但是Vector是同步的。由Vector创徏的IteratorQ虽然和ArrayList创徏的Iterator是同一接口Q但是,因ؓ(f)Vector是同步的Q当一个Iterator被创且正在被用,另一个线E改变了Vector的状态(例如Q添加或删除了一些元素)(j)Q这时调用Iterator的方法时抛出ConcurrentModificationExceptionQ因此必L莯异常?/FONT>

Stack c?BR>  Stackl承自VectorQ实C个后q先出的堆栈。Stack提供5个额外的Ҏ(gu)使得Vector得以被当作堆栈用。基本的push和popҎ(gu)Q还有peekҎ(gu)得到栈顶的元素,emptyҎ(gu)试堆栈是否为空QsearchҎ(gu)(g)一个元素在堆栈中的位置。Stack刚创建后是空栈?/FONT>

Set接口
  Set是一U不包含重复的元素的CollectionQ即L的两个元素e1和e2都有e1.equals(e2)=falseQSet最多有一个null元素?BR>  很明显,Set的构造函数有一个约束条Ӟ传入的Collection参数不能包含重复的元素?BR>  h意:(x)必须心操作可变对象QMutable ObjectQ。如果一个Set中的可变元素改变了自w状态导致Object.equals(Object)=true导致一些问题?/FONT>

Map接口
  h意,Map没有l承Collection接口QMap提供key到value的映。一个Map中不能包含相同的keyQ每个key只能映射一个value。Map接口提供3U集合的视图QMap的内容可以被当作一lkey集合Q一lvalue集合Q或者一lkey-value映射?/FONT>

Hashtablec?BR>  Hashtablel承Map接口Q实C个key-value映射的哈希表。Q何非I(non-nullQ的对象都可作ؓ(f)key或者value?BR>  d数据使用put(key, value)Q取出数据用get(key)Q这两个基本操作的时间开销为常数?BR>Hashtable通过initial capacity和load factor两个参数调整性能。通常~省的load factor 0.75较好地实C旉和空间的均衡。增大load factor可以节省I间但相应的查找旉增大,q会(x)影响像get和putq样的操作?BR>使用Hashtable的简单示例如下,?Q?Q?攑ֈHashtable中,他们的key分别是”one”,”two”,”three”:(x)
    Hashtable numbers = new Hashtable();
    numbers.put(“one? new Integer(1));
    numbers.put(“two? new Integer(2));
    numbers.put(“three? new Integer(3));
  要取Z个数Q比?Q用相应的keyQ?BR>    Integer n = (Integer)numbers.get(“two?;
    System.out.println(“two = ?+ n);
  ׃作ؓ(f)key的对象将通过计算其散列函数来定与之对应的value的位|,因此M作ؓ(f)key的对象都必须实现hashCode和equalsҎ(gu)。hashCode和equalsҎ(gu)l承自根cObjectQ如果你用自定义的类当作key的话Q要相当心Q按照散列函数的定义Q如果两个对象相同,即obj1.equals(obj2)=trueQ则它们的hashCode必须相同Q但如果两个对象不同Q则它们的hashCode不一定不同,如果两个不同对象的hashCode相同Q这U现象称为冲H,冲突?x)导致操作哈希表的时间开销增大Q所以尽量定义好的hashCode()Ҏ(gu)Q能加快哈希表的操作?BR>  如果相同的对象有不同的hashCodeQ对哈希表的操作?x)出现意想不到的l果Q期待的getҎ(gu)q回nullQ,要避免这U问题,只需要牢C条:(x)要同时复写equalsҎ(gu)和hashCodeҎ(gu)Q而不要只写其中一个?BR>  Hashtable是同步的?/FONT>

HashMapc?BR>  HashMap和HashtablecMQ不同之处在于HashMap是非同步的,q且允许nullQ即null value和null key。,但是HashMap视ؓ(f)CollectionӞvalues()Ҏ(gu)可返回CollectionQ,其P代子操作旉开销和HashMap的容量成比例。因此,如果q代操作的性能相当重要的话Q不要将HashMap的初始化定w讑־q高Q或者load factorq低?/FONT>

WeakHashMapc?BR>  WeakHashMap是一U改q的HashMapQ它对key实行“弱引用”,如果一个key不再被外部所引用Q那么该key可以被GC回收?/FONT>

ȝ
  如果涉及(qing)到堆栈,队列{操作,应该考虑用ListQ对于需要快速插入,删除元素Q应该用LinkedListQ如果需要快速随问元素,应该使用ArrayList?BR>  如果E序在单U程环境中,或者访问仅仅在一个线E中q行Q考虑非同步的c,其效率较高,如果多个U程可能同时操作一个类Q应该用同步的cR?BR>  要特别注意对哈希表的操作Q作为key的对象要正确复写equals和hashCodeҎ(gu)?BR>  量q回接口而非实际的类型,如返回List而非ArrayListQ这样如果以后需要将ArrayList换成LinkedListӞ客户端代码不用改变。这是针对抽象~程?BR>
[b]同步?BR>Vector是同步的。这个类中的一些方法保证了Vector中的对象是线E安全的。而ArrayList则是异步的,因此ArrayList中的对象q不是线E安全的。因为同步的要求?x)?jing)响执行的效率Q所以如果你不需要线E安全的集合那么使用ArrayList是一个很好的选择Q这样可以避免由于同步带来的不必要的性能开销?BR>数据增长
从内部实现机制来讲ArrayList和Vector都是使用数组(Array)来控刉合中的对象。当你向q两U类型中增加元素的时候,如果元素的数目超Z内部数组目前的长度它们都需要扩展内部数l的长度QVector~省情况下自动增长原来一倍的数组长度QArrayList是原来的50%,所以最后你获得的这个集合所占的I间L比你实际需要的要大。所以如果你要在集合中保存大量的数据那么使用Vector有一些优势,因ؓ(f)你可以通过讄集合的初始化大小来避免不必要的资源开销?BR>使用模式
在ArrayList和Vector中,从一个指定的位置Q通过索引Q查找数据或是在集合的末֢加、移除一个元素所p的时间是一L(fng)Q这个时间我们用O(1)表示。但是,如果在集合的其他位置增加或移除元素那么花费的旉?x)呈UŞ增长QO(n-i)Q其中n代表集合中元素的个数Qi代表元素增加或移除元素的索引位置。ؓ(f)什么会(x)q样呢?以ؓ(f)在进行上q操作的时候集合中Wi和第i个元素之后的所有元素都要执行位Uȝ操作。这一切意味着什么呢Q?BR>q意味着Q你只是查找特定位置的元素或只在集合的末端增加、移除元素,那么使用Vector或ArrayList都可以。如果是其他操作Q你最好选择其他的集合操作类。比如,LinkList集合cd增加或移除集合中M位置的元素所p的时间都是一L(fng)—O(1)Q但它在索引一个元素的使用~比较慢QO(i),其中i是烦(ch)引的位置.使用ArrayList也很Ҏ(gu)Q因Z可以单的使用索引来代替创建iterator对象的操作。LinkList也会(x)为每个插入的元素创徏对象Q所有你要明白它也会(x)带来额外的开销?BR>最后,在《Practical Java》一书中Peter Haggar使用一个简单的数组QArrayQ来代替Vector或ArrayList。尤其是对于执行效率要求高的E序更应如此。因Z用数l?Array)避免了同步、额外的Ҏ(gu)调用和不必要的重新分配空间的操作?/FONT>