java中有好多集合:List,ArrayList,Vector,HashSetTreeSet,它們之間的區別,java集合的框架等等總是很模糊,稱有時間總結下。
一、Collection接口和Iterator接口
1.Collection框架:
collection接口主要定義了一些操作集合元素的方法:
|
Ensures that this collection contains the specified element (optional operation).如果插入成功,返回true |
|
addAll Adds all of the elements in the specified collection to this collection (optional operation).改變返回true |
|
clear Removes all of the elements from this collection (optional operation). |
|
Returns true if this collection contains the specified element. |
|
containsAll Returns true if this collection contains all of the elements in the specified collection. |
|
Compares the specified object with this collection for equality. |
|
hashCode Returns the hash code value for this collection. |
。。。。。。具體可看文檔
2.使用Iterator接口遍歷幾何元素
Iterrator接口隱藏了各種Collection實現類的細節,向應用程序提供了遍歷Collection集合元素的統一編程接口。Iterator接口里定義了如下三個方法:
Boolean hashNext(): 如果被迭代的集合元素還沒有被遍歷,則返回true.
Object next(): 返回集合里的下一個元素。
Void remove(): 刪除集合里上一次next方法返回的元素。
**當使用Iterator迭代訪問Collection集合元素時,Collection集合里的元素不能被改變,只有通過Iterator的remove方法刪除上一次next方法返回的集合元素才可以;否則將引發java.util.Concurrent ModificationException異常。
下面開始一個個類介紹
二、set集合
Set集合的方法與Collection基本上完全一樣,它沒有提供額外的方法。實際上Set就是Collection,只是行為略有不同(Set不允許包含重復元素)。
Set判斷兩個對象是否相同是根據equals方法。也就是說,只要兩個對象用equals方法方法比較返回false,Set就會接受這兩個對象。
1.HashSet是Set的典型實現,HashSet按Hash算法來存儲集合中的元素,因此具有很好的存取和查找性能。
特點:不能保證元素的排列順序;不是同步的,不是線程安全;集合值可以是null。
HashSet集合判斷兩個元素的相等的標准是兩個對象通過equals方法比較相等,並且兩個對象的hashCode()方法返回值也相等。
示例:
import java.util.*; //類A的equals方法總是返回true,但沒有重寫其hashCode()方法 class A { public boolean equals(Object obj) { return true; } } //類B的hashCode()方法總是返回1,但沒有重寫其equals()方法 class B { public int hashCode() { return 1; } } //類C的hashCode()方法總是返回2,但沒有重寫其equals()方法 class C { public int hashCode() { return 2; } public boolean equals(Object obj) { return true; } } public class TestHashSet { public static void main(String[] args) { HashSet books = new HashSet(); //分別向books集合中添加2個A對象,2個B對象,2個C對象 books.add(new A()); books.add(new A()); books.add(new B()); books.add(new B()); books.add(new C()); books.add(new C()); System.out.println(books); } }
輸出:[B@1, B@1, C@2, A@659e0bfd, A@2a139a55]
可以看出HashSet把A,B當成兩個對象,C只有一個。
2.LinkedHashSet類
LinkedHashSet集合同樣是根據元素的hashCode值來決定元素的存儲位置,但是它同時使用鏈表維護元素的次序。這樣使得元素看起 來像是以插入順序保存的,也就是說,當遍歷該集合時候,LinkedHashSet將會以元素的添加順序訪問集合的元素。
LinkedHashSet在迭代訪問Set中的全部元素時,性能比HashSet好,但是插入時性能稍微遜色於HashSet。
import java.util.*; public class TestLinkedHashSet { public static void main(String[] args) { LinkedHashSet books = new LinkedHashSet(); books.add("第一個"); books.add("第二個"); //刪除 Struts2權威指南 books.remove("第一個"); //重新添加 Struts2權威指南 books.add("第一個"); System.out.println(books);//[第二個, 第一個] } }
輸出:[第二個, 第一個] 可以看到順序是按插入順序排列的。
3.TreeSet類
TreeSet是SortedSet接口的實現類,TreeSet可以確保集合元素處於排序狀態。TreeSet支持兩種排序方式,自然排序 和定制排序,其中自然排序為默認的排序方式。向TreeSet中加入的應該是同一個類的對象。
TreeSet判斷兩個對象不相等的方式是兩個對象通過equals方法返回false,或者通過CompareTo方法比較沒有返回0。向TreeSet中添加的應該是同一個類的對象,且最好是不可變對象。
1.自然排序
自然排序使用要排序元素的CompareTo(Object obj)方法來比較元素之間大小關系,然后將元素按照升序排列。
Java提供了一個Comparable接口,該接口里定義了一個compareTo(Object obj)方法,該方法返回一個整數值,實現了該接口的對象就可以比較大小。
obj1.compareTo(obj2)方法如果返回0,則說明被比較的兩個對象相等,如果返回一個正數,則表明obj1大於obj2,如果是 負數,則表明obj1小於obj2。
如果我們將兩個對象的equals方法總是返回true,則這兩個對象的compareTo方法返回應該返回0
import java.util.*; class R implements Comparable { int count; public R(int count) { this.count = count; } public String toString() { return "R(count屬性:" + count + ")"; } public boolean equals(Object obj) { if (obj instanceof R) { R r = (R)obj; if (r.count == this.count) { return true; } } return false; } public int compareTo(Object obj) { R r = (R)obj; if (this.count > r.count) { return 1; } else if (this.count == r.count) { return 0; } else { return -1; } } } public class TestTreeSet2 { public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add(new R(5)); ts.add(new R(-3)); ts.add(new R(9)); ts.add(new R(-2)); //打印TreeSet集合,集合元素是有序排列的 System.out.println(ts); //取出第一個元素 R first = (R)ts.first(); //為第一個元素的count屬性賦值 first.count = 20; //取出最后一個元素 R last = (R)ts.last(); //為最后一個元素的count屬性賦值,與倒數第二個元素count屬性相同 last.count = -2; //再次輸出count將看到TreeSet里的元素處於無序狀態,且有重復元素 System.out.println(ts); //刪除屬性被改變的元素,刪除失敗 ts.remove(new R(-2)); System.out.println(ts); //刪除屬性沒有改變的元素,刪除成功 ts.remove(new R(5));
ts.remove(new R(20)); System.out.println(ts); } }
輸出結果:
/*
---------- java運行 ----------
[R(count屬性:-3), R(count屬性:-2), R(count屬性:5), R(count屬性:9)]
[R(count屬性:20), R(count屬性:-2), R(count屬性:5), R(count屬性:-2)] //這里改變之后並沒有重新排序,所以TreeSet中最好放不可改變的對象。
[R(count屬性:20), R(count屬性:-2), R(count屬性:5), R(count屬性:-2)] //刪除-2失敗,因為屬性被改變
[R(count屬性:20), R(count屬性:-2), R(count屬性:-2)] //沒有改變的5可以刪除
輸出完成 (耗時 0 秒) - 正常終止*/
2.定制排序
自然排序是根據集合元素的大小,以升序排列,如果要定制排序,應該使用Comparator接口,實現 int compare(T o1,T o2)方法,該方法用於比較o1和o2的大小:如果該方法返回正整數,則表示o1大於o2;如果方法返回0,則表示o1等於o2,如果該方法返回負整數,則表示o1小於o2。
如果需要定制排序,則需要在創建TreeSet集合時提供一個Comparator對象與該TreeSet集合關聯,由Comparator對象負責幾何元素的排序邏輯:
import java.util.*; class M { int age; public M(int age) { this.age = age; } public String toString(){ return "M age:"+age; } } public class TestTreeSet3 { public static void main(String[] args) { TreeSet ts = new TreeSet(new Comparator() { public int compare(Object o1, Object o2) { /*int age1 = o1 instanceof M ? ((M)o1).age :((N)o1).age; int age2 = o1 instanceof M ? ((M)o2).age :((N)o2).age; return age1 - age2;*/ M m1 = (M)o1; M m2 = (M)o2; if (m1.age > m2.age) { return -1; } else if (m1.age == m2.age) { return 0; } else { return 1; } } }); ts.add(new M(5)); ts.add(new M(-3)); ts.add(new M(9)); System.out.println(ts);//[M age:9, M age:5, M age:-3] } }
輸出結果·(降序):[M age:9, M age:5, M age:-3]
4.各Set實現類比較:
HashSet和TreeSet是set的兩個典型實現,HashSet的性能比TreeSet好(特別是最常用的添加,查詢元素等操作).只有當需要一個保持排序的Set時,才應該使用TreeSet,否則使用HashSet
LinkedHashSet:對於普通的插入刪除操作,比HashSet慢,遍歷會更快。
另外:Set的三個實現類HashSet,TreeSet和EnemSet都是線程不安全的,如果有多個線程訪問一個Set集合,則必須手動保持同步:
可用Collections的工具類:例如:
SortedSet s = Collections.synchronizedSortedSet(new TreeSet(…));
Set集合終於總結完啦。。
這篇已經夠長啦,List集合在下一篇。。。
轉發請注明:http://www.cnblogs.com/jycboy/p/set.html