Java学习之容器上(Collection接口常用方法,Iterator接口,使用foreach循环遍历Collection集合元素,Set集合通用知识(Hashset类,hashcode()与Lin
1.容器API的類圖結(jié)構(gòu)如下:
?
?
JAVA的集合類是一種特別有用的工具類,它可以用于存儲(chǔ)數(shù)量不等的多個(gè)對(duì)象,并可以實(shí)現(xiàn)常用數(shù)據(jù)結(jié)構(gòu),如棧,隊(duì)列等,除此之外,JAVA集合還可用于保存具有映射關(guān)系的關(guān)聯(lián)數(shù)組。
?
JAVA的集合大致上可分為:Set,List和Map三種體系,其中Set代表無(wú)序,不可重復(fù)的集合;List代表有序,重復(fù)的集合,而Map則代表具有遇敵關(guān)系的集合。Queue體系集合,代表一種隊(duì)列集合實(shí)現(xiàn)。
?
JAVA集合概述:
?
?JAVA提供集合類主要負(fù)責(zé)保存盛裝其他數(shù)據(jù),因此集合類也被稱為容器類。所有集合類都位于java.util包下。
?
JAVA集合類主要由兩個(gè)接口派生而出:Collection和Map,也是根接口。
Map保存的每項(xiàng)數(shù)據(jù)都是key-value對(duì),也就是由key和value兩個(gè)值組成。
?
下面給個(gè)比喻,再給個(gè)圖就非常容易理解了。
?
JAVA的所有集合分成三大類,其中Set 集合類似于一個(gè)罐子,把一個(gè)對(duì)象添加到Set集合時(shí),Set集合無(wú)法記住添加這個(gè)元素的順序,所以Set里的元素不能重復(fù)(否則系統(tǒng)無(wú)法準(zhǔn)確識(shí)別這個(gè)元素)
?
List集合非常像一個(gè)數(shù)組,它可以記住每次添加元素的順序,只是List長(zhǎng)度可變。
?
Map集合也像一個(gè)罐子,只是它里面的每項(xiàng)數(shù)據(jù)都由兩個(gè)值組成。
如果訪問(wèn)List集合中的元素,可以直接根據(jù)元素的索引來(lái)訪問(wèn),如果需要訪問(wèn)Map集合中的元素,可以根據(jù)每項(xiàng)元素的key來(lái)訪問(wèn)其value,如果希望訪問(wèn)Set集合中的元素,則只能根據(jù)元素本身來(lái)訪問(wèn)(這也是Set集合里元素不允許重復(fù)的原因)
?
對(duì)于Set,List和Map三種集合,最常用的實(shí)現(xiàn)類,分別是HashSet,ArrayList? ,,HashMap? 三個(gè)實(shí)現(xiàn)類。
?
1.1?Collection接口:
Collection接口——定義了存取一組對(duì)象的方法,其子接口Set和List分別定義了存儲(chǔ)方式。
(1)Set中的數(shù)據(jù)對(duì)象沒(méi)有順序且不可以重復(fù)。
(2)List中的數(shù)據(jù)對(duì)象有順序且可以重復(fù)。
Collection接口所定義的方法:
| 方法 | 描述 |
| Boolean add(Object o) | 向集合中添加一個(gè)對(duì)象的引用 |
| Void clear() | 刪除集合中的所有對(duì)象,即不再持有這些對(duì)象的引用 |
| Boolean contains(Object o) | 判斷在集合中是否持有特定對(duì)象的引用 |
| Boolean isEmpty() | 判斷集合是否為空 |
| Iterator iterator() | 返回一個(gè)Iterator對(duì)象,可用它來(lái)遍歷集合中的元素 |
| Boolean remove(Object o) | 從集合中刪除一個(gè)對(duì)象的引用 |
| ?Boolean retainAll(Collection<?> c) | 保留集合中的指定內(nèi)容? |
| Int size() | 返回集合中元素的數(shù)目 |
| Object[] toArray() | 返回一個(gè)數(shù)組,該數(shù)組包含集合中的所有元素 ? |
| Boolean equals(Object o) | 對(duì)象比較 |
| Int hashCode()? | 返回hash碼 |
?
?注意:相等的對(duì)象應(yīng)該具有相等的 hash codes。容器類對(duì)象在調(diào)用remove,contains等方法時(shí)需要比較對(duì)象是否相等,這回涉及到對(duì)象類型的equals方法和hasCode方法;對(duì)于自定義的類型,需要重寫equals和hashCode方法以實(shí)現(xiàn)自定義的對(duì)象相等規(guī)則。
?Set接口和list接口都繼承了Collection接口,而map接口沒(méi)有繼承Collection接口,因此可以對(duì)set對(duì)象和list對(duì)象調(diào)用以上方法,但是不能對(duì)Map對(duì)象調(diào)用以上方法。
Collection接口的iterator()和toArray()方法都用于獲取集合中的所有元素,前者返回一個(gè)Iterator對(duì)象,后者放回一個(gè)包含集合中所有元素的數(shù)組。
?
增加Name類的equals和hashCode方法如下:
1 public boolean equals(Object obj){ 2 if(obj instanceof Name){ 3 Name name=(Name)obj; return(firstName.equals(name.firstName)&&lastName.equals(name.lastName));4 } 5 return super.equals(obj); 6 } 7 public int hashCode(){ 8 return firstName.hashCode(); 9 }
?
方法應(yīng)用例子:
1 import java.util.ArrayList; 2 import java.util.Collection; 3 import java.util.HashSet; 4 public class TestCollection{ 5 public static void main(String[] args){ 6 Collection c= new ArrayList(); 7 c.add("孫悟空"); 8 c.add(6); 9 System.out.println("c集合的元素的個(gè)數(shù)為:"+c.size()); 10 System.out.println("c集合里面是否包含孫悟空字符"+" "+c.contains("孫悟空")); 11 c.add("世界你好"); 12 System.out.println("c集合里面的元素:"+c); 13 Collection books=new HashSet(); //HashSet不允許元素重復(fù)。 14 books.add("世界你好"); 15 books.add("你好世界"); 16 System.out.println("c集合里面是否完全包含books:"+c.contains(books)); 17 c.removeAll(books); 18 System.out.println("c集合中的元素:"+c); 19 c.clear(); 20 System.out.println("c集合里面的元素:"+c); 21 books.retainAll(c); 22 System.out.println("books集合的元素:"+books); 23 24 } 25 }?
?輸出結(jié)果:
c集合的元素的個(gè)數(shù)為:2
c集合里面是否包含孫悟空字符 true
c集合里面的元素:[孫悟空, 6, 世界你好]
c集合里面是否完全包含books:false
c集合中的元素:[孫悟空, 6]
c集合里面的元素:[]
books集合的元素:[]
?
?1.2 Iterator接口:
使用Iterator接口遍歷集合元素,Iterator接口是JAVA集合框架的成員,也被稱為迭代器。
Iterator接口中聲明了如下方法:
?boolean hashNext():如果迭代的集合元素還沒(méi)被遍歷,則返回true
Object next():返回集合里下一個(gè)元素。
Void remove():刪除集合里上一次next方法返回的元素。
?
1 import java.util.Collection; 2 import java.util.HashSet; 3 import java.util.Iterator; 4 public class TextIterator { 5 public static void main(String[] args){ 6 Collection books=new HashSet(); //無(wú)序序列,元素不可重復(fù) 7 books.add("世界你好"); 8 books.add("你好世界"); 9 books.add("你好Java"); 10 System.out.println("現(xiàn)在結(jié)合的元素:"+books); 11 Iterator it=books.iterator(); //獲取books集合對(duì)應(yīng)的迭代器。 12 while(it.hasNext()){ 13 String book=(String)it.next(); //it.next()方法返回的數(shù)據(jù)類型是object類型,需要強(qiáng)制類型轉(zhuǎn)換。 14 System.out.println(book); 15 if(book.equals("你好世界")){ 16 it.remove(); //從集合中刪除上一次next方法返回的元素。 17 } 18 book="測(cè)試字符串"; //對(duì)book變量賦值,不會(huì)改變集合元素本身。 19 } 20 System.out.println(books); 21 22 23 }?
?
?輸出結(jié)果:
現(xiàn)在結(jié)合的元素:[世界你好, 你好Java, 你好世界]
世界你好
你好Java
你好世界
[世界你好, 你好Java]
Iterator僅用于遍歷集合,Iterator本身并不提供盛裝對(duì)象的能力,如果需要?jiǎng)?chuàng)建Iterator對(duì)象,則必須有一個(gè)被迭代的集合。
Iterator必須依附于Collection對(duì)象,有一個(gè)Iterator對(duì)象,則必然有一個(gè)懷之關(guān)聯(lián)的Collection對(duì)象。Iterator提供了2個(gè)方法來(lái)迭代訪問(wèn)Collection集合里的元素。
結(jié)論:當(dāng)使用Iterator對(duì)集合元素進(jìn)行迭代時(shí),Iterator并不是把集合元素本身傳給了迭代變量,而是把集合元素的值傳給了迭代變量,所以修改迭代變量的值對(duì)集合元素本身沒(méi)有任何改變。
?
1.3使用foreach循環(huán)遍歷集合元素
我們知道,除了可以使用Iterator類迭代訪問(wèn)Collection集合里的元素之外,現(xiàn)在還可以使用foreach循環(huán)來(lái)迭代訪問(wèn)集合元素會(huì)更加便捷。
foreach的語(yǔ)句格式: for(元素類型t 元素變量x : 遍歷對(duì)象obj){ ???? 引用了x的java語(yǔ)句; }?
1 import java.util.Collection; 2 import java.util.HashSet; 3 4 public class TextForeach { 5 public static void main(String[] args){ 6 Collection books=new HashSet(); 7 books.add("世界您好"); 8 books.add("您好世界"); 9 books.add("您好JAVA"); 10 for(Object obj:books){ 11 String book=(String)obj; //此處的book變量也不是集合元素本身 12 System.out.println(book); 13 if(book.equals("您好世界")) { 14 books.remove(book); 15 } 16 17 } 18 19 System.out.println(books); 20 21 }?
輸出結(jié)果:
現(xiàn)在結(jié)合的元素:[世界你好, 你好Java, 你好世界]
世界你好
你好Java
你好世界
[世界你好, 你好Java]
?
1.4 Set集合的通用知識(shí):
1.4.1HashSet類:
HashSet是Set接口的典型實(shí)現(xiàn),大多數(shù)時(shí)候使用Set集合時(shí)就是使用這個(gè)實(shí)現(xiàn)類。HashSet按Hash算法一存儲(chǔ)集合中的元素,因此具有很好的存取和查找性能。
特點(diǎn):
》不能保證元素的排列順序,順序有可能發(fā)生變化。
》HashSet來(lái)是同步的,如果多個(gè)線程同時(shí)訪問(wèn)一個(gè)Set集合,如果多個(gè)線程同時(shí)訪問(wèn)一個(gè)HashSet,如果有2條或者2條以上線程同時(shí)修改了HashSet集合,必須通過(guò)代碼來(lái)保證其同步。
》集合元素值可以是Null
我們可以簡(jiǎn)單的認(rèn)為:HashSet集合判斷兩個(gè)元素相等的標(biāo)準(zhǔn)是兩個(gè)對(duì)象通過(guò)equals方法比較相等,并且兩個(gè)對(duì)象的hashCode()方法返回值也相等。
?
1 import java.util.*; 2 class A{ //類A的equals方法總是返回true,但沒(méi)有重寫其hashCode()方法 3 public boolean equals(Object obj){ 4 return true; 5 } 6 } 7 class B{ //類B的hashCode()方法總是返回l,但沒(méi)有重寫equals()方法 8 public int hashCode(){ 9 return 1; 10 } 11 } 12 class C{ //類C的hashCode()方法總是返回2,重寫其equals()方法 13 public int hashCode(){ 14 return 2; 15 } 16 public boolean equals(Object obj){ 17 return true; 18 } 19 } 20 public class TextHashset{ 21 public static void main(String[] args){ 22 HashSet books = new HashSet(); 23 books.add(new A()); 24 books.add(new A()); 25 books.add(new B()); 26 books.add(new B()); 27 books.add(new C()); 28 books.add(new C()); 29 30 } 31 }?
?
我們從編譯結(jié)果可以看出,即使2個(gè)A對(duì)象通過(guò)equals比較返回true,但HashSet依然把它們當(dāng)成2個(gè),即使2個(gè)B對(duì)象的hashCode()返回相同值(都是1)但,HashSet依然把它們當(dāng)成2個(gè)對(duì)象。
?
簡(jiǎn)單的提醒點(diǎn):
如果需要某個(gè)類的對(duì)象保存到HashSet集合中,重寫這個(gè)類的equals()方法和hashCode()方法時(shí),應(yīng)該盡量保證兩個(gè)對(duì)象通過(guò)equals比較返回true時(shí),它們的hashCode方法返回值也相等。
HashSet采用每個(gè)元素的hashCode作為其索引,從而可以自由增加HashSet的長(zhǎng)度,并可以根據(jù)元素的hashCode值來(lái)訪問(wèn)該元素。
(我們可以理解為相當(dāng)于數(shù)組里的下標(biāo)索引)。
?
因?yàn)閔ashCode()方法很重要,看看重寫hashCode()方法的基本規(guī)則。
》當(dāng)兩個(gè)對(duì)象通過(guò)equals方法比較返回true時(shí),這個(gè)兩個(gè)對(duì)象的hashCode應(yīng)該相等。
》對(duì)象中用作equals比較標(biāo)準(zhǔn)的屬性,都應(yīng)該用來(lái)計(jì)算hashCode值。
?
?
?
1 import java.util.Iterator; 2 3 class R{ 4 int count; 5 public R(int count){ 6 this.count=count; 7 } 8 public String toString(){ 9 return "R[count"+count+"]"; 10 } 11 public boolean equals(Object obj){ 12 if(obj instanceof R){ 13 R f=(R)obj; 14 if(f.count==this.count){ 15 return true; 16 } 17 } 18 return false; 19 } 20 public int hashCode(){ 21 return this.count; 22 } 23 } 24 public class TestHashSet2{ 25 public static void main(String[] args){ 26 HashSet hs=new HashSet(); 27 hs.add(new R(5)); 28 hs.add(new R(-3)); 29 hs.add(new R(9)); 30 hs.add(new R(-2)); 31 System.out.println("第1個(gè)hs,集合中的元素:"+hs+"\n"); //打印HashSet集合,集合元素沒(méi)有重復(fù) 32 Iterator it=hs.iterator(); 33 R first = (R)it.next(); 34 first.count = -3; //為第一個(gè)元素的count實(shí)例變量賦值 35 System.out.println("第2個(gè)hs,集合中的元素:"+hs+"\n"); 36 hs.remove(new R(-3)); //刪除count為-3的R對(duì)象 37 System.out.println("第3個(gè)hs,集合中的元素:"+hs+"\n"); 38 System.out.println("hs是否包含count為-3的R對(duì)象?"+hs.contains(new R(-3))); //輸出false 39 System.out.println("hs是否包含count為5的R對(duì)象"+hs.contains(new R(5))); //輸出false 40 } 41 }?
?
輸出結(jié)果:
第1個(gè)hs,集合中的元素:[R[count5], R[count9], R[count-3], R[count-2]]
第2個(gè)hs,集合中的元素:[R[count-3], R[count9], R[count-3], R[count-2]]
第3個(gè)hs,集合中的元素:[R[count-3], R[count9], R[count-2]]
hs是否包含count為-3的R對(duì)象?false
hs是否包含count為5的R對(duì)象false
?
ps:
(1)object類中的hashcode()方法比較的是對(duì)象的地址(引用地址),使用new方法創(chuàng)建對(duì)象,兩次生成的當(dāng)然是不同的對(duì)象,造成的結(jié)果就是兩個(gè)對(duì)象的hashcode()返回的值不一樣。所以hashset會(huì)把new方法創(chuàng)建的兩個(gè)它們當(dāng)作不同的對(duì)象對(duì)待,
(2)在java的集合中,判斷兩個(gè)對(duì)象是否相等的規(guī)則是:?
a),判斷兩個(gè)對(duì)象的hashCode是否相等?
????? 如果不相等,認(rèn)為兩個(gè)對(duì)象也不相等,完畢?
????? 如果相等,轉(zhuǎn)入2)?
(這一點(diǎn)只是為了提高存儲(chǔ)效率而要求的,其實(shí)理論上沒(méi)有也可以,但如果沒(méi)有,實(shí)際使用時(shí)效率會(huì)大大降低,所以我們這里將其做為必需的。)?
b),判斷兩個(gè)對(duì)象用equals運(yùn)算是否相等?
????? 如果不相等,認(rèn)為兩個(gè)對(duì)象也不相等?
????? 如果相等,認(rèn)為兩個(gè)對(duì)象相等(equals()是判斷兩個(gè)對(duì)象是否相等的關(guān)鍵)?
?
LinkedHashSet類:
HashSet還有一個(gè)子類LinkedHashSet,它也是根據(jù)元素hashCode值來(lái)決定元素存儲(chǔ)位置,它是需要維護(hù)元素的插入順序,因此性能略低于HashSet的性能,但在迭代訪問(wèn)Set里的全部元素時(shí)將有很好的性能,因?yàn)樗枣湵韥?lái)維護(hù)內(nèi)部順序。
1 import java.util.LinkedHashSet; 2 public class LinkedHashSetTest{ 3 public static void main(String[] args){ 4 LinkedHashSet books = new LinkedHashSet(); 5 books.add("世界您好"); 6 books.add("您好世界"); 7 System.out.println(books); 8 books.remove("世界您好"); //刪除世界您好 9 books.add("世界您好"); //重新添加世界您好 10 System.out.println(books); 11 } 12 }?
?輸出結(jié)果:
[世界您好, 您好世界]
[您好世界, 世界您好]
編譯結(jié)果相信大家都理解,因?yàn)樵氐捻樞蛘门c添加順序一致。
from:?http://www.cnblogs.com/shide/archive/2013/03/30/2982755.html
總結(jié)
以上是生活随笔為你收集整理的Java学习之容器上(Collection接口常用方法,Iterator接口,使用foreach循环遍历Collection集合元素,Set集合通用知识(Hashset类,hashcode()与Lin的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Thinking in java基础之集
- 下一篇: Java书籍Top 10