Java程式設計入門筆記(十一)
海納百川——物件陣列和集合
物件陣列
陣列 在Java提供的儲存及隨機訪問物件序列的各種方法中,陣列是效率最高的一種
- 型別檢查
- 邊界檢查
優點
- 陣列知道其元素的型別
- 編譯時的型別檢查
- 大小已知
代價
- 陣列物件的大小是固定的,在生存期內大小不可變
物件陣列
- 陣列元素是類的物件
- 所有元素具有相同的型別
- 每個元素都是一個物件的引用
靜態初始化:在宣告和定義陣列的同時對陣列元素進行初始化,例如:
BankAccount[] accounts = {
new BankAccount(“Zhang", 100.00),
new BankAccount (“Li", 2380.00),
new BankAccount(“Wang", 500.00),
new BankAccount(“Liu", 175.56),
new BankAccount(“Ma", 924.02)};
動態初始化:使用運算子new,需要經過兩步: 首先給陣列分配空間
type arrayName[ ]=new type[arraySize];
然後給每一個數組元素分配空間
arrayName[0]=new type(paramList);
…
arrayName[arraySize-1] =new type(paramList);
Java集合框架
- 程式設計師不需要關心你的陣列到底該申請多少個元素,框架會自動幫你分配空間
- 程式設計師可以通過一個鍵,快速得到這個鍵所對應的值,並且不需要顧慮插入和刪除元素的問題
- 程式設計師可以方便地對資料進行排序、遍歷等
- 程式設計師可以直接使用各種資料結構
Java集合框架提供了一套效能優良、使用方便的介面和類,它們位於java.util包中
Collection 介面儲存一組不唯一,無序的物件
List 介面儲存一組不唯一,有序(插入順序)的物件
Set 介面儲存一組唯一,無序的物件
Map介面儲存一組鍵值物件,提供key(唯一)到value的對映
List類集合
ArrayList實現了長度可變的陣列,在記憶體中分配連續的空間。遍歷元素和隨機訪問元素的效率比較高
LinkedList採用連結串列儲存方式(離散空間)。插入、刪除元素時效率比較高
List介面常用方法小結 LinkedList的特殊方法 插入元素對比
隨機訪問對比
Vector類
-
另外一個常用的列表類是Vector類,它也實現了List介面,可以實現ArrayList的所有操作。
-
Vector和ArrayList的異同
- 實現原理、功能相同,可以互用
- 主要區別 Vector執行緒安全操作相對較慢 ArrayList重速度輕安全,執行緒非安全 長度需增長時,Vector預設增長一倍,ArrayList增長50% Vector可以使用capacity()方法獲取實際的空間
ArrayList和Vector的預設初始大小均為10
Set類集合
如果確定元素在列表中不能重複,那麼可以使用Set Set無法隨機訪問,要訪問其元素,只能使用迭代器遍歷
Set支援的操作
- boolean add(E e);
- void clear();
- boolean contains(Object o);
- boolean isEmpty();
- boolean remove(Object o);
- int size();
HashSet:保證在Set中的元素唯一,但是不保證元素的順序恆久不變(加入新元素後,元素的遍歷順序可能發生改變)。
TreeSet:保證Set中的元素唯一,並且對元素按其自然順序進行排序。
-
TreeSet特有的操作:
- E first();
- E last();
- E ceiling(E e);
- E floor(E e);
- E lower(E e);
- E higher(E e);
- void poolFirst();
- void poolLast();
對比
HashSet | TreeSet |
---|---|
保證元素唯一 | 保證元素唯一 |
元素在集合中的順序不定(並且和放入順序無關) | 保證元素排序 |
使用equals()方法和hashCode()方法來保證元素唯一性 | 通過對元素比較判斷其結果是否為0來保證元素唯一性 元素可以實現Comparable介面也可以使用Comparator來比較元素 |
低層資料結構:雜湊連結串列 | 低層資料結構:二叉樹 |
演算法
Java中的演算法都封裝在類Arrays和Collections中
排序(Sorting) 使用Arrays.sort()方法可以對陣列進行排序
使用Collections.sort()方法可以對集合進行排序
排序演算法:
- 當處理原始資料型別時,演算法為快速排序
- 當處理物件型別時,演算法為歸併排序
亂序(Shuffling) 亂序就是做和排序相反的工作,將資料隨機地打亂順序。
生活中的亂序:洗牌。
常規資料處理演算法 reverse:將一個List中的元素反向排列
fill:用指定的值覆寫List中的每一個元素,這個操作在重新初始化List時有用
copy::接受兩個引數,目標List和源List,將源中的元素複製到目標,覆寫其中的內容。目標List必須至少與源一樣長,如果更長,則多餘的部分內容不受影響
查詢演算法binarySearch 使用二分法在一個有序的List中查詢指定元素 有兩種形式
- 第一種形式假定List是按照自然順序升序排列的
- 第二種形式需要增加一個Comparator物件,表示比較規則,並假定List是按照這種規則排序的。
尋找最值——用於任何集合物件 min和max演算法返回指定集合中的最小值和最大值 這兩個演算法分別都有兩種形式 簡單形式按照元素的自然順序返回最值 另一種形式需要附加一個Comparator物件作為引數,並按照Comparator物件指定的比較規則返回最值
Map類集合
Map介面專門處理鍵值對映資料的儲存,可以根據鍵實現對值的操作 最常用的實現類是HashMap
例子
Map countries = new HashMap();
countries.put("CN", "中華人民共和國");
countries.put("RU", "俄羅斯聯邦");
countries.put("FR", "法蘭西共和國");
countries.put("US", "美利堅合眾國");
//使用HashMap儲存多組鍵值對
String country = (String) countries.get("CN");
//獲取指定元素的值
System.out.println("Map中共有"+countries.size() +"組資料");
//獲取Map元素個數
countries.remove("FR");
System.out.println("Map中包含FR的key嗎?" + countries.containsKey("FR"));
//刪除指定元素,判斷是否包含指定元素
System.out.println( countries.keySet() ) ;
System.out.println( countries.values() );
System.out.println( countries );
//顯示鍵集、值集和鍵值對集
Map介面常用方法
查詢方法
方法名 | 說明 |
---|---|
int size() | 返回Map中的元素個數 |
boolean isEmpty() | 返回Map中是否包含元素,如不包括任何元素,則返回true |
boolean containsKey(Object key) | 判斷給定的引數是否是Map中的一個關鍵字(key) |
boolean containsValue(Object val) | 判斷給定的引數是否是Map中的一個值(value) |
Object get(Object key) | 返回Map中與給定關鍵字相關聯的值(value) |
Collection values() | 返回包含Map中所有值(value)的Collection物件 |
Set keySet() | 返回包含Map中所有關鍵字(key)的Set物件 |
Set entrySet() | 返回包含Map中所有項的Set物件 |
修改方法
方法名 | 說明 |
---|---|
Object put(Object key, Object val) | 將給定的關鍵字(key)/值(value)對加入到Map物件中。其中關鍵字(key)必須唯一,否則,新加入的值會取代Map物件中已有的值 |
void putAll(Map m) | 將給定的引數Map中的所有項加入到接收者Map物件中 |
Object remove(Object key) | 將關鍵字為給定引數的項從Map物件中刪除 |
void clear() | 從Map物件中刪除所有的項 |
雜湊表 也稱為散列表,是用來儲存群體物件的集合類結構,其兩個常用的類是HashTable及HashMap
雜湊表相關的一些主要概念
名詞 | 說明 |
---|---|
容量(capacity) | 雜湊表的容量不是固定的,隨物件的加入,其容量可以自動擴充 |
關鍵字/鍵(key) | 每個儲存的物件都需要有一個關鍵字key,key可以是物件本身,也可以是物件的一部分(如物件的某一個屬性) |
雜湊碼(hash code) | 要將物件儲存到HashTable,就需要將其關鍵字key對映到一個整型資料,稱為key的雜湊碼(hash code) |
雜湊函式(hash function) | 返回物件的雜湊碼 |
項(item) | 雜湊表中的每一項都有兩個域:關鍵字域key及值域value(即儲存的物件)。key及value都可以是任意的Object型別的物件,但不能為空(null),HashTable中的所有關鍵字都是唯一的 |
裝填因子(load factor) | (表中填入的項數)/(表的容量) |
構造方法
- Hashtable( ); // 初始容量為101,最大裝填因子為0.75
- Hashtable(int capacity);
- Hashtable(int capacity, float maxLoadFactor);
雜湊表常用函式
方法名 | 說明 |
---|---|
Object put(Object key, Object value) | 值value以key為其關鍵字加入到雜湊表中,如果此關鍵字在表中不存在,則返回null,否則表中儲存的value |
Object get(Object key) | 返回關鍵字為key的值value,如果不存在,則返回null。 |
Object remove(Object key) | 將鍵/值對從表中去除,並返回從表中去除的值,如果不存在,則返回null。 |
boolean isEmpty() | 判斷雜湊表是否為空 |
boolean containsKey(Object key) | 判斷給定的關鍵字是否在雜湊表中 |
boolean contains(Object value) | 判斷給定的值是否在雜湊表中 |
boolean containsValue(Object value) | 判斷給定的值是否在雜湊表中 |
void clear() | 將雜湊表清空 |
Enumeration elements() | 返回包含值的Enumeration物件 |
Enumeration keys() | 返回包含關鍵字的Enumeration物件 |
HashMap類與HashTable類很相似,只是HashTable類不允許有空的關鍵字,而HashMap類允許
HashMap和Hashtable的比較 實現原理、功能相同,可以互用 主要區別
- Hashtable繼承Dictionary類,HashMap實現Map介面
- Hashtable執行緒安全,HashMap執行緒非安全
- Hashtable不允許null值,HashMap允許null值
不涉及到多執行緒的開發過程中,最好使用ArrayList和HashMap 如果程式中用到多執行緒,酌情使用Vector和Hashtable
集合遍歷與迭代器(Iterator)
如何遍歷List, Set和Map集合呢? 方法1:迴圈(僅適用於List) 方法2:增強型for迴圈(foreach迴圈,適用於所有類) 方法3:通過迭代器Iterator實現遍歷
- 獲取Iterator :Collection 介面的iterate()方法
- Iterator的方法 boolean hasNext(): 判斷是否存在另一個可訪問的元素 Object next(): 返回要訪問的下一個元素
方法4:(僅適用於JDK 1.8) 適用forEach()方法
Iterator介面 也是一個遍歷集合元素的工具,是對Enumeration介面的改進,因此在遍歷集合元素時,優先選用Iterator介面
與Enumeration不同,具有從正在遍歷的集合中去除物件的能力
具有如下三個例項方法,可見相對於Enumerationo介面簡化了方法名
- hasNext() —— 判斷是否還有元素
- next() —— 取得下一個元素
- remove() —— 去除一個元素。注意是從集合中去除最後呼叫
- next()返回的元素,而不是從Iterator類中去除
遍歷Map例項
Set keys=dogMap.keySet(); //取出所有key的集合
Iterator it=keys.iterator(); //獲取Iterator物件
while(it.hasNext()){
String key=(String)it.next(); //取出key
Dog dog=(Dog)dogMap.get(key); //根據key取出對應的值
System.out.println(key+"\t"+dog.getStrain());
}
//迭代器Iterator
///////////////////////////////////////////////////
for(元素型別t 元素變數x : 陣列或集合物件){
引用了x的java語句
}
//增加for型迴圈
///////////////////////////////////////////////////
Set keys=dogMap.keySet();
Keys.forEach(new DogConsumer()); //新建一個匿名物件
class DogConsumer implements Consumer {
public void accept(Object obj) { //每個Set中的物件,都會呼叫一次該方法
}
}
//JDK 1.8 之後可以使用forEach方法遍歷集合
Enumeration Enumeration介面不能用於ArrayList物件,而Iterator介面既可以用於ArrayList物件,也可以用於Vector物件
Enumeration介面 (1.0版) 提供了兩個例項方法
- hasMoreElements() —— 判斷是否還有剩下的元素;
- nextElement() —— 取得下一個元素。
遍歷集合類物件v中的每個元素可使用下面程式碼完成:
Enumeration e = v.elements();
while (e.hasMoreElements()) {
Customer c = (Customer)v.nextElement();
System.out.println(c.getName());
}