Object類:完整的類最好覆寫Object類的hashCode()
句喷,equals()
镣典,toString()
3個(gè)方法。
在類集中提供了4種常見的輸出方式:
- Iterator:迭代輸出唾琼,使用最多的輸出方式兄春。
- ListIterator:Iterator的子接口,專門用于輸出List中的內(nèi)容锡溯。
- Enumeration:是舊接口赶舆,功能與Iterator類似。
- foreach:jdk1.5之后新增趾唱,輸出數(shù)組和集合涌乳。
Iterator——迭代器:
- 二要素:
i. 迭代器必定從屬于某個(gè)容器,其作用就是用來遍歷所屬容器中的元素的甜癞。
ii.迭代器是在容器的數(shù)據(jù)視圖之上進(jìn)行迭代,因此不能再迭代過程中修改容器中的數(shù)據(jù)宛乃,否則會(huì)拋出異常悠咱!除非使用迭代器的專用方法對(duì)數(shù)據(jù)進(jìn)行修改。 - Java的迭代器只在
Collection
中有征炼,而Map沒有迭代器析既,它有不同的迭代方法。 - 迭代器的終極目標(biāo):就是用統(tǒng)一的方法來迭代不同類型的集合谆奥!可能由于不同集合的內(nèi)部數(shù)據(jù)結(jié)構(gòu)不盡相同眼坏,如果要自己純手工迭代的話相互之間會(huì)有很大的差別,而迭代器的作用就是統(tǒng)一的方法對(duì)不同的集合進(jìn)行迭代酸些,而在迭代器底層隱藏不同集合之間的差異宰译,從而為迭代提供最大的方便檐蚜。
- 用迭代器迭代的步驟:
i. 第一步肯定是先獲取集合的迭代器:調(diào)用集合的iterator方法就能獲得,Iterator<E> Collection.iterator();
// 是Collection的對(duì)象方法
ii. 使用迭代器的hasNext沿侈、next往下迭代闯第。
Iterator的常用方法:
* boolean hasNext(); // 是否還有下一個(gè)元素(肯定有一個(gè)位置指針維護(hù)者當(dāng)前迭代的位置)
* Object next(); // 取出下一個(gè)元素并返回
* void remove(); // 從容器中刪除當(dāng)前元素(即上一個(gè)next代表的那個(gè)元素),直接會(huì)改變?nèi)萜髦械臄?shù)據(jù)缀拭!
?由于Java容器都是泛型類模板咳短,因此容器可以記憶元素的具體類型,因此可以放心使用蛛淋,只不過取出元素后要進(jìn)行類型轉(zhuǎn)換后才能正常使用,
使用迭代器next獲得的元素是一個(gè)集合中對(duì)應(yīng)元素的深拷貝(即數(shù)據(jù)視圖)咙好,如果對(duì)迭代變量進(jìn)行修改是不會(huì)修改集合中的原數(shù)據(jù)的。同樣褐荷,也不能直接在迭代過程中使用c.remove等方法對(duì)集合進(jìn)行修改敷扫,因?yàn)榈饕呀?jīng)鎖定住集合了,強(qiáng)行修改會(huì)拋出異常诚卸!只能用Iterator的專用修改集合元素的方法修改才是正確的葵第,就像上面的Iterator.remove方法澜倦。
模板:
public class Test {
public static void main(String[] args) {
Collection c = new ArrayList(); // ArrayList是Collection的一個(gè)實(shí)現(xiàn)類辅柴,默認(rèn)元素類型為Object
Iterator it = c.iterator();
while (it.hasNext()) {
Type var = it.next(); // 迭代值(數(shù)據(jù)視圖)
對(duì)var進(jìn)行操作;
c.remove(); // 錯(cuò)誤2榭狻缭付!在迭代過程中使用非迭代器方法對(duì)集合進(jìn)行修改會(huì)直接拋出異常O省榔袋!
}
}
}
實(shí)際上西壮,Iterator迭代的“集合”是真正集合的視圖串述,視圖和真實(shí)數(shù)據(jù)之間是一一映射的關(guān)系睛约,如果此時(shí)使用非迭代器方法對(duì)真實(shí)數(shù)據(jù)進(jìn)行修改就會(huì)導(dǎo)致真實(shí)數(shù)據(jù)和映像之間不一致鼎俘,因此會(huì)拋出異常,而迭代器的修改方法可以保證這種映射的一致性辩涝,即迭代器先對(duì)視圖進(jìn)行修改贸伐,然后將視圖的修改更新到真實(shí)數(shù)據(jù),但是反向就是無效的怔揩,因?yàn)橛诚褡约菏侵狸P(guān)聯(lián)的是哪個(gè)真實(shí)數(shù)據(jù)捉邢,但是真實(shí)數(shù)據(jù)本身不知道有哪些映像和我關(guān)聯(lián)的,即真實(shí)數(shù)據(jù)永遠(yuǎn)是被動(dòng)的商膊,而映像是主動(dòng)的伏伐。
ListIterator
ListIterator
是Iterator的子接口,專門用于輸出List中的內(nèi)容晕拆。只能從List接口實(shí)例化藐翎。可以進(jìn)行雙向迭代。
public class ListIteratorDemo01{
public static void main(String argsp[]){
List<String> all = new ArrayList<String>() ;
all.add("hello") ;
all.add("_") ;
all.add("world") ;
ListIterator<String> iter = all.listIterator() ;
System.out.print("由前向后輸出:") ;
while(iter.hasNext()){
String str = iter.next() ;
System.out.print(str + "吝镣、") ;
}
System.out.print("\n由后向前輸出:") ;
while(iter.hasPrevious()){
String str = iter.previous() ;
System.out.print(str + "堤器、") ;
}
}
};
輸出結(jié)果:
由前向后輸出:hello、赤惊、world吼旧、
由后向前輸出:world、未舟、hello圈暗、
- 在使用ListIterator接口進(jìn)行雙向輸出時(shí),如果想完成由后向前輸出則一定要先進(jìn)行由前往后輸出裕膀。
- foreach也可以輸出集合员串。for(類 : 對(duì)象 集合)
- Enumeration 廢棄的接口,舊類昼扛,已被擴(kuò)充寸齐。
Map接口
Map 就是關(guān)聯(lián)數(shù)組,也常被稱為“映射表”或是“字典”抄谐,是鍵值對(duì)的集合容器渺鹦,鍵不能重復(fù)出現(xiàn)是他的基本限制
如上圖所示,Map 都繼承自 Map 接口蛹含,標(biāo)準(zhǔn) Java 類庫中包含了幾種 Map 的基本實(shí)現(xiàn):
- TreeMap -- 基于紅黑樹的 Map 實(shí)現(xiàn)毅厚,因此是有序的,作為鍵加入 TreeMap 的對(duì)象必須實(shí)現(xiàn) Comparable 接口浦箱,以便他可以被比較
- HashMp -- 基于哈希表的 Map 實(shí)現(xiàn)吸耿,雖然無序,但是優(yōu)勢(shì)卻在于其查詢速度
- LinkedHaskMap -- 在 HashMap 的基礎(chǔ)上實(shí)現(xiàn)的雙鏈表復(fù)合結(jié)構(gòu)酷窥,在查詢速度的基礎(chǔ)上保證了插入順序
- WeakHashMap -- WeakHashMap 與 HashMap 的用法基本相同咽安,Hash 的 key 保留對(duì)象的強(qiáng)引用,即只要 HashMap 5. 對(duì)象不被銷毀蓬推,其對(duì)象所有 key 所引用的對(duì)象不會(huì)被垃圾回收妆棒,HashMap 也不會(huì)自動(dòng)刪除這些key所對(duì)應(yīng)的鍵值對(duì)對(duì)象。但 WeakHashMap 的 key 所引用的對(duì)象沒有被其他強(qiáng)引用變量所引用拳氢,則這些 key 所引用的對(duì)象可能被回收募逞。WeakHashMap 中的每個(gè) key 對(duì)象保存了實(shí)際對(duì)象的弱引用馋评,當(dāng)回收了該 key 所對(duì)應(yīng)的實(shí)際對(duì)象后留特,WeakHashMap 會(huì)自動(dòng)刪除該key所對(duì)應(yīng)的鍵值對(duì)
- ConcurrentHashMap -- ConcurrentHashMap 保證了線程安全,一般用在多線程環(huán)境中
- IdentityHashMap -- 與 HashMap 一樣蜕青,IdentityHashMap 也不保證存儲(chǔ)的順序,他與 HashMap 的區(qū)別在于右核,它用來比較鍵是否相同的方法是 == 而不是 equals 方法,因此值相同但地址不同的兩個(gè)對(duì)象是允許出現(xiàn)的贺喝,一般只在解決特殊問題時(shí)才會(huì)使用
Map 接口定義了基本的 map 操作方法:
方法名 | 方法 | 說明 |
---|---|---|
get | V get(Object key) | 獲取 key 對(duì)應(yīng)的值 |
put | V put(K key, V value) | 向容器中添加鍵值對(duì) |
putAll | void putAll(Map m) | 將 Map m 中的所有元素添加到容器中 |
remove | V remove(Object key) | 刪除指定的 key |
clear | void clear() | 清除容器中所有元素 |
containsKey | boolean containsKey(Object key) | 判斷 key 是否存在 |
containsValue | boolean containsValue(Object value) | 判斷 value 是否存在 |
isEmpty | boolean isEmpty() | 判斷容器是否為空 |
keySet | Set keySet() | 返回由所有 key 組成的 set |
values | Collection values() | 返回由所有 value 組成的 Collection |
entrySet | Set> entrySet(); | 獲取 Map 內(nèi)部接口 Entry 組成的 Set |
TreeMap : String類型實(shí)現(xiàn)了comparable接口,如果使用自定義類的話需要先實(shí)現(xiàn)Comparable
接口躏鱼。
對(duì)象的四種引用方式:
- 強(qiáng)引用
強(qiáng)引用是最常見的的一種引用,類似"Object obj = new Object()"之類的引用染苛,只要強(qiáng)引用還存在鹊漠,垃圾收集器永遠(yuǎn)不會(huì)回收掉被引用對(duì)象。 - 軟引用 軟引用是用來描述一些還有用但并非必需的對(duì)象茶行。對(duì)于軟引用的對(duì)象躯概,在系統(tǒng)將要發(fā)生內(nèi)存溢出之前,會(huì)把這些對(duì)象列入回收范圍之中進(jìn)行第二次回收畔师。如果這次回收還沒有足夠的內(nèi)存娶靡,才會(huì)拋出溢出異常。JDK1.2之后使用SoftReference來實(shí)現(xiàn)軟引用茉唉。
- 弱引用
弱引用用來描述非必需的對(duì)象固蛾,但是強(qiáng)度比軟引用更弱一些,被弱引用關(guān)聯(lián)的對(duì)象只能生存到下一次垃圾收集器工作時(shí)度陆,無論當(dāng)前內(nèi)存是否足夠艾凯,都會(huì)回收弱引用所關(guān)聯(lián)的對(duì)象。JDK1.2之后使用WeakReference來實(shí)現(xiàn)弱引用懂傀。 - 虛引用
虛引用又稱幽靈引用或者幻影引用趾诗,他是最弱的一種引用關(guān)系。一個(gè)對(duì)象是否有虛引用的存在蹬蚁,完全不會(huì)對(duì)其生存時(shí)間存在影響恃泪,也無法通過虛引用來獲取一個(gè)對(duì)象實(shí)例。為一個(gè)對(duì)象設(shè)置虛引用關(guān)聯(lián)的唯一目的就是能在這個(gè)對(duì)象被收集器回收時(shí)收到一個(gè)系統(tǒng)通知犀斋。JDK1.2之后使用PhantomReference來實(shí)現(xiàn)虛引用贝乎。
總結(jié):強(qiáng)引用的對(duì)象一定不會(huì)被當(dāng)成垃圾回收的,軟引用的對(duì)象會(huì)在內(nèi)存不足時(shí)被當(dāng)成垃圾回收掉叽粹,弱引用的對(duì)象在下一次垃圾回收時(shí)就直接回收掉览效。
Map接口的注意事項(xiàng):
- 不能直接使用迭代(Iterator,foreach)輸出Map中的全部?jī)?nèi)容却舀。如果要用需按照以下4步。
a. 將map的實(shí)例通過entrySet()方法變?yōu)镾et接口對(duì)象锤灿。
b. 通過Set接口實(shí)例為Iterator實(shí)例化挽拔。
c. 通過Iterator迭代輸出,每個(gè)內(nèi)容都是Map.Entry的對(duì)象但校。
d. 通過Map.Entry進(jìn)行key→value的分離螃诅。
- 使用Iterator輸出Map實(shí)例
public class IteratorDemo04 {
public static void main(String[] args) {
Map<String, String> map = null; // 聲明Map對(duì)象,其中key和value的類型為String
map = new HashMap<String,String>();
map.put("lc", "lichuang"); // 增加內(nèi)容
map.put("jsf", "jisaifu"); // 增加內(nèi)容
map.put("wzc", "wangzhicheng"); // 增加內(nèi)容
Set<Map.Entry<String, String>> allSet = null;
allSet = map.entrySet();
Iterator<Map.Entry<String, String>> iter = null;
iter = allSet.iterator();
while (iter.hasNext()) {
Map.Entry<String, String> me = iter.next();
System.out.println(me.getKey() + "-->" + me.getValue());
}
}
}
執(zhí)行結(jié)果:
wzc-->wangzhicheng
lc-->lichuang
jsf-->jisaifu
- 使用foreach輸出Map實(shí)例:
public class ForeachDemo02{
public static void main(String args[]){
Map<String,String> map = null; // 聲明Map對(duì)象状囱,其中key和value的類型為String
map = new HashMap<String,String>() ;
map.put("lc", "lichuang"); // 增加內(nèi)容
map.put("jsf", "jisaifu"); // 增加內(nèi)容
map.put("wzc", "wangzhicheng"); // 增加內(nèi)容
for(Map.Entry<String,String> me:map.entrySet()){
System.out.println(me.getKey() + " --> " + me.getValue()) ;
}
}
}
如果要使用一個(gè)自定義的對(duì)象表示Map中的key术裸,則對(duì)象所在類中一定要覆寫equals()和hashCode()方法,否則無法找到對(duì)應(yīng)的value浪箭。
class Person{
private String name ;
private int age ;
public Person(String name,int age){
this.name = name ;
this.age = age ;
}
public String toString(){
return "姓名:" + this.name + "穗椅;年齡:" + this.age ;
}
public boolean equals(Object obj){
if(this==obj){
return true ;
}
if(!(obj instanceof Person)){
return false ;
}
Person p = (Person)obj ;
if(this.name.equals(p.name)&&this.age==p.age){
return true ;
}else{
return false ;
}
}
public int hashCode(){
return this.name.hashCode() * this.age ;
}
};
public class HashMapDemo08{
public static void main(String args[]){
Map<Person,String> map = null ;
map = new HashMap<Person,String>() ;
map.put(new Person("張三",30),"zhangsan"); // 增加內(nèi)容
System.out.println(map.get(new Person("張三",30))) ;
}
}