標籤:out 抽象 基本 http st3 lang class 成功 new t
一、集合的由來
通常,我們的程式需要根據程式運行時才知道建立多少個對象。但若非程式運行,程式開發階段,我們根本不知道到底需要多少個數量的對象,甚至不知道它的準確類型。為了滿足這些常規的編程需要,我們要求能在任何時候,任何地點建立任意數量的對象,而這些對象用什麼來容納呢?我們首先想到了數組,但是數組只能放統一類型的資料,而且其長度是固定的,那怎麼辦呢?集合便應運而生了!
二、集合是什嗎?
Java集合類存放於 java.util 包中,是一個用來存放對象的容器。
注意:①、集合只能存放對象。比如你存一個 int 型資料 1放入集合中,其實它是自動轉換成 Integer 類後存入的,Java中每一種基本類型都有對應的參考型別。
②、集合存放的是多個對象的引用,對象本身還是放在堆記憶體中。
③、集合可以存放不同類型,不限數量的資料類型。
三、Java 集合架構圖
上述類圖中,實線邊框的是實作類別,比如ArrayList,LinkedList,HashMap等,折線邊框的是抽象類別,比如AbstractCollection,AbstractList,AbstractMap等,而點線
邊框的是介面,比如Collection,Iterator,List等。右下角的 Collections 和 Arrays 是兩個協助類。
發現一個特點,上述所有的集合類,都實現了Iterator介面,這是一個用於遍曆集合中元素的介面,主要包含 hashNext(),next(),remove()三種方法。它的一個子介面
LinkedIterator在它的基礎上又添加了三種方法,分別是 add(),previous(),hasPrevious()。也就是說如果是先Iterator介面,那麼在遍曆集合中元素的時候,只能往後遍曆,被
遍曆後的元素不會在遍曆到,通常無序集合實現的都是這個介面,比如HashSet,HashMap;而那些元素有序的集合,實現的一般都是 LinkedIterator介面,實現這個介面的集合
可以雙向遍曆,既可以通過next()訪問下一個元素,又可以通過previous()訪問前一個 元素,比如ArrayList。
還有一個特點就是抽象類別的使用。如果要自己實現一個集合類,去實現那些抽象的介面會非常麻煩,工作量很大。這個時候就可以使用抽象類別,這些抽象類別中給我們提供了許多
現成的實現,我們只需要根據自己的需求重寫一些方法或者添加一些方法就可以實現自己需要的集合類,工作量大大降低。
四、集合詳解
①、Iterator:迭代器,它是Java集合的頂層介面(不包括 map 系列的集合,Map介面 是 map 系列集合的頂層介面)
Object next():返回迭代器剛越過的元素的引用,傳回值是 Object,需要強制轉換成自己需要的類型
boolean hasNext():判斷容器內是否還有可供訪問的元素
void remove():刪除迭代器剛越過的元素
所以除了 map 系列的集合,我們都能通過迭代器來對集合中的元素進行遍曆。
注意:我們可以在源碼中追溯到集合的頂層介面,比如 Collection 介面,可以看到它繼承的是類 Iterable
那這就得說明一下 Iterator 和 Iterable 的區別:
Iterable :存在於 java.lang 包中。
我們可以看到,裡面封裝了 Iterator 介面。所以只要實現了只要實現了Iterable介面的類,就可以使用Iterator迭代器了。
Iterator :存在於 java.util 包中。核心的方法next(),hasnext(),remove()。
這裡我們引用一個Iterator 的實作類別 ArrayList 來看一下迭代器的使用:暫時先不管 List 集合是什麼,只需要看看迭代器的用法就行了
1 //產生一個 List 集合,典型實現為 ArrayList。 2 List list = new ArrayList(); 3 //添加三個元素 4 list.add("Tom"); 5 list.add("Bob"); 6 list.add("Marry"); 7 //構造 List 的迭代器 8 Iterator it = list.iterator(); 9 //通過迭代器遍曆元素10 while(it.hasNext()){11 Object obj = it.next();12 System.out.println(obj);13 }
②、Collection:List 介面和 Set 介面的父介面
看一下 Collection 集合的使用例子:
1 //我們這裡將 ArrayList集合作為 Collection 的實作類別 2 Collection collection = new ArrayList(); 3 4 //添加元素 5 collection.add("Tom"); 6 collection.add("Bob"); 7 8 //刪除指定元素 9 collection.remove("Tom");10 11 //刪除所有元素12 Collection c = new ArrayList();13 c.add("Bob");14 collection.removeAll(c);15 16 //檢測是否存在某個元素17 collection.contains("Tom");18 19 //判斷是否為空白20 collection.isEmpty();21 22 //利用增強for迴圈遍曆集合23 for(Object obj : collection){24 System.out.println(obj);25 }26 //利用迭代器 Iterator27 Iterator iterator = collection.iterator();28 while(iterator.hasNext()){29 Object obj = iterator.next();30 System.out.println(obj);31 }
③、List :有序,可以重複的集合。
由於 List 介面是繼承於 Collection 介面,所以基本的方法如上所示。
1、List 介面的三個典型實現:
①、List list1 = new ArrayList();
底層資料結構是數組,查詢快,增刪慢;線程不安全,效率高
②、List list2 = new Vector();
底層資料結構是數組,查詢快,增刪慢;安全執行緒,效率低,幾乎已經淘汰了這個集合
③、List list3 = new LinkedList();
底層資料結構是鏈表,查詢慢,增刪快;線程不安全,效率高
怎麼記呢?我們可以想象:
數組就像身上編了號站成一排的人,要找第10個人很容易,根據人身上的編號很快就能找到。但插入、刪除慢,要望某個位置插入或刪除一個人時,後面的人身上的編號都要變。當然,加入或刪除的人始終末尾的也快。
鏈表就像手牽著手站成一圈的人,要找第10個人不容易,必須從第一個人一個個數過去。但插入、刪除快。插入時只要解開兩個人的手,並重新牽上新加進來的人的手就可以。刪除一樣的道理。
2、除此之外,List 介面遍曆還可以使用普通 for 迴圈進行遍曆,指定位置添加元素,替換元素等等。
1 //產生一個 List 集合,典型實現為 ArrayList 2 List list = new ArrayList(); 3 //添加三個元素 4 list.add("Tom"); 5 list.add("Bob"); 6 list.add("Marry"); 7 //構造 List 的迭代器 8 Iterator it = list.iterator(); 9 //通過迭代器遍曆元素10 while(it.hasNext()){11 Object obj = it.next();12 //System.out.println(obj);13 }14 15 //在指定地方添加元素16 list.add(2, 0);17 18 //在指定地方替換元素19 list.set(2, 1);20 21 //獲得指定對象的索引22 int i=list.indexOf(1);23 System.out.println("索引為:"+i);24 25 //遍曆:普通for迴圈26 for(int j=0;j<list.size();j++){27 System.out.println(list.get(j));28 }
④、Set:不可以重複的集合。
1、Set hashSet = new HashSet();
HashSet:不能保證元素的順序;不可重複;不是安全執行緒的;集合元素可以為 NULL;
對於 HashSet: 如果兩個對象通過 equals() 方法返回 true,這兩個對象的 hashCode 值也應該相同。 * 當向HashSet集合中存入一個元素時,HashSet會調用該對象的hashCode()方法來得到該對象的hashCode值然後根據hashCode值決定該對象在HashSet中的儲存位置 * 如果兩個元素的equals()方法返回true,但他們的hashCode()傳回值不相等,hashSet將會把它們儲存在不同的位置,但依然可以添加成功! 2、Set treeSet = new TreeSet(); TreeSet:有序;不可重複 * 如果使用 TreeSet() 無參數的構造器建立一個 TreeSet 對象, 則要求放入其中的元素的類必須實現 Comparable 介面所以, 在其中不能放入 null 元素 *
必須放入同樣類的對象.(預設會進行排序) 否則可能會發生類型轉換異常. * 兩個對象通過 Comparable 介面 compareTo(Object obj) 方法的傳回值來比較大小, 並進行升序排列 * 當需要把一個對象放入 TreeSet 中,重寫該對象對應的 equals() 方法時,應保證該方法與 compareTo(Object obj) 方法有一致的結果 * 定製排序: 建立 TreeSet 對象時, 傳入 Comparator 介面的實作類別. 要求: Comparator 介面的 compare 方法的傳回值和 兩個元素的 equals() 方法具有一致的傳回值
Java 集合的理解(持續更新......)