轉載自 http://yeniu33zmz.blog.163.com/blog/static/28961848200982844927347/
java集合大致上可分爲:set,list,map三種體系,其中set代表無序不可重複的集合,list代表有序可重複的集合,map代表具有映射關係的集合。後來又增加一種Queue體系集合,代表一種隊列的集合實現。
set和list接口都實現了collection接口
使用Iterator接口遍歷集合元素
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
public class TestIterator {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//創建一個集合
Collection books = new HashSet();
books.add("book1");
books.add("book2");
books.add("book3");
books.add("book4");
//獲取Iterator迭代器
Iterator it = books.iterator();
while(it.hasNext()){
//it.next()方法返回的數據類型是Object類型,需要強制類型轉換
String book = (String)it.next();
System.out.println(book);
if(book.equals("book3")){
//從集合中***上一次next返回的元素
it.remove();
//使用Iterator迭代器過程中,不可修改集合元素,所以下面代碼引發異常
//books.remove("book3");
}
//對book變量賦值,不會改變元素本身
book= "book9";
}
System.out.println(books);
}
}
Iterator必須依附於Collection對象。有一個Iterator對象,則必然有一個與之關聯的的Collection對象。
使用foreach遍歷集合元素更加簡潔
import java.util.Collection;
import java.util.HashSet;
public class TestIterator {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//創建一個集合
Collection books = new HashSet();
books.add("book1");
books.add("book2");
books.add("book3");
books.add("book4");
for(Object obj : books)
{
String book = (String)obj;
System.out.println(book);
if(book.equals("book3")){
//使用循環過程中,不可修改集合元素,所以下面代碼引發異常
//books.remove("book3");
}
}
System.out.println(books);
}
}
Set接口
實際上Set就是Collection,只是Set不允許包含重複元素
Set通過equals方法判斷兩個對象是否相同,而不是==,所以只要equals返回true,
那麼兩個對象就是相同的,無論實際上這兩個對象差別有多大,而只要equals返回false,即使兩個對象實際上是同一個對象,Set也會當成兩個對象處理。
例如:
import java.util.HashSet;
import java.util.Set;
public class TestSet {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Set books = new HashSet();
books.add("book1");
boolean result = books.add(new String("book1"));
System.out.println(result);
System.out.println(books);
}
}
將輸出false book1
HashSet,TreeSet,EnumSet三個類實現了Set接口
HashSet類
HashSet具有的特點:
1 不能保證元素的排列順序,順序可能發生變化。
2 HashSet不是同步的,如果多個線程同時訪問一個Set集合,如果多個線程同時訪問一個HashSet,如果有2條或者以上的線程修改了 HashSet集合時,必須通過代碼來保證其是同步的(TreeSet和EnumSet也一樣)。
3 集合元素可以是null。
HashSet判斷兩個元素相等是的標準是兩個對象通過equals方法比較相等,並且兩個對象的hashCode方法返回的值也相等。
如果equals比較相等,hashCode返回值不同,則HashSet將會把兩個對象保存到不同的位置,即都添加成功
如果equals不相等,hashCode返回值相等,則HashSet將會試圖把兩個對象保存到同一個位置,實際上又不行,處理起來將很複雜,將導致性能下降。
所以,重寫某個類的equals方法和hashCode方法時,應該儘量保證對象通過equals返回true是,它們的hashCode返回值也相等。
重寫hashCode的基本規則
1 過equals返回true是,它們的hashCode返回值也相等
2 對象中用作equals比較標準的屬性,都應該用來計算hashCode值。
當向HashSet中添加可變對象是,必須非常的小心,如果修改HashSet中的對象時,有可能導致該對象與集合中的其他對象相等,從而導致HashSet無法準確訪問該對象。
HashSet的子對象LinkedHashSet使用鏈表維護元素次序,使元素以插入順序保存,性能略低於HashSet。
TreeSet類
TreeSet是SortedSet接口的唯一實現,可以確保元素處於排序狀態
TreeSet通用方法示例:
import java.util.TreeSet;
public class TestTreeSet {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet nums = new TreeSet();
//向TreeSet添加4個Integer對象
nums.add(5);
nums.add(2);
nums.add(10);
nums.add(-9);
//輸出集合元素
System.out.println(nums);
//輸出集合裏的第一個元素
System.out.println(nums.first());
//輸出集合裏的最後一個元素
System.out.println(nums.last());
//返回小於4的子集、不包含4
System.out.println(nums.headSet(4));
//返回大於5的子集、包含5
System.out.println(nums.tailSet(5));
//返回大於-3,小於4的子集
System.out.println(nums.subSet(-3, 4));
}
}
與HashSet集合採用hash算法來決定元素的存儲位置不同,TreeSet集合採用紅黑樹的數據結構來對元素進行排序,分自然排序和定製排序倆種,默認的情況下采用自然排序。
試圖把一個對象添加到TreeSet時,該對象的類必須實現Comparable接口,否則出現異常(添加第一個時沒事,添加第二個時,TreeSet調用該對象的CompareTo(Object obj)方法時引發異常),而且向TreeSet添加的對象應該屬於同一個類的對象,否則也會引發異常。
一些常用類已經實現了Comparable接口,比如BigDecimal,BigInteger,Character,Boolean(true>false),String,Date,Time等
對於TreeSet而言,判斷兩個對象不相等的標準是:equals方法返回false,或compareTO方法沒有返回0,即使兩個對象是同一個對象也會當做兩個對象處理。所有當重寫一個須放入TreeSet的類的equals方法時,應該保證與compareTo方法有一致的結果。
如果向TreeSet中添加一個可變對象後,並且後面的程序修改了該對象的屬性,導致它與其他對象的大小發生了變化,但TreeSet不會再次調整它們的順序,甚至導致保存的這兩個對象通過equals返回true,而compareTo確返回0,所有推薦HashSet和TreeSet集合中只放入不可變對象。
示例:
import java.util.TreeSet;
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 true;
}
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 {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet ts = new TreeSet();
ts.add(new R(5));
ts.add(new R(-3));
ts.add(new R(9));
ts.add(new R(-2));
System.out.println(ts);
// 取出第一個元素
R frist = (R)ts.first();
//改變其屬性值
frist.count = 20;
//取出最後一個元素
R last = (R)ts.last();
//改變其屬性值
last.count = -2;
System.out.println(ts);
//***已更改的元素失敗
ts.remove(new R(-2));
System.out.println(ts);
//***未更改的元素成功
ts.remove(new R(5));
System.out.println(ts);
}
}
EnumSet
EnumSet是一個專門爲枚舉類設計的集合,內部以向量的方式存儲,佔用內存很少,運行效率很高
EnumSet不允許加入null元素,否則會出現異常
當試圖複製一個Collection集合裏的元素來創建EnumSet集合時,必須保證Collection集合裏的所有元素都是同一個枚舉類的枚舉值。
示例:
import java.util.EnumSet;
enum Season{
SPRING,SUMMER,FALL,WINTER;
}
public class EnumSetDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
EnumSet es1 = EnumSet.allOf(Season.class);
System.out.println(es1);
EnumSet es2 = EnumSet.noneOf(Season.class);
System.out.println(es2);
es2.add(Season.WINTER);
es2.add(Season.SPRING);
System.out.println(es2);
//輸出summer,winter
EnumSet es3 = EnumSet.of(Season.SUMMER,Season.WINTER);
System.out.println(es3);
//輸出summer,fall,winter
EnumSet es4 = EnumSet.range(Season.SUMMER, Season.WINTER);
System.out.println(es4);
//獲得es4的餘集
EnumSet es5 = EnumSet.complementOf(es4);
//輸出spring
System.out.println(es5);
}
}