[转]Java中常用的集合—初学者的你不可错过的精编整理
集合一直都是項目中非常常見的,我是一個Android開發(fā)者,集合對于我來說,在項目中使用的次數(shù)非常之多,因為使用的多,熟能生巧,所以這里呢!就給那些初學者整理一下Java當中常用的集合吧!?
??因為此篇文章是給初學者看到,所以對于集合的認識,我們就不從內(nèi)存的角度去分析了,等你Java學到一定的時候,再去學習一下集合的底層實現(xiàn),這會讓成為一名更加牛的Java程序員。?
??在整理之前呢,我們先聊一聊為什么集合會這么常用?,集合這個概念,我們初次接觸是在高中的數(shù)學當中,高中的集合具有以下知識點:?
1、集合的含義:某些指定的對象集在一起就成為一個集合,其中每一個對象叫元素。
2、集合的中元素的三個特性:
①.元素的確定性;②.元素的互異性;③.元素的無序性
說明:?
? (1)對于一個給定的集合,集合中的元素是確定的,任何一個對象或者是或者不是這個給定的集合的元素。
(2)任何一個給定的集合中,任何兩個元素都是不同的對象,相同的對象歸入一個集合時,僅算一個元素。
(3)集合中的元素是平等的,沒有先后順序,因此判定兩個集合是否一樣,僅需比較它們的元素是否一樣,不需考查排列順序是否一樣。?
??高中的集合理解起來很簡單,高中的集合里面放到是一個一個具體的對象,集合當中對象與對象之間是不一樣的,而且集合中對象的元素是雜亂無章的,順序沒有什么規(guī)律可循,因為高中集合是無序性的。那么Java當中的集合是否又和高中的集合的概念是一致的呢?答案肯定不是啦,因為Java當中的集合是基于數(shù)據(jù)結(jié)構(gòu)實現(xiàn)的,這些數(shù)據(jù)結(jié)構(gòu)包括有:數(shù)組,鏈表,隊列,棧,哈希表,樹……等等,而高中的集合顯然和這搭不上邊,如果你不太懂這些數(shù)據(jù)結(jié)構(gòu),那么學起集合來可以說是非常吃力的,所以在學集合之前,請先小小的理解一些數(shù)據(jù)結(jié)構(gòu),因為你要想成為一名Java開發(fā)大神,數(shù)據(jù)結(jié)構(gòu)你必須拿下!這里我貼一個數(shù)據(jù)結(jié)構(gòu)自學的教學視頻:?
??鏈接:http://pan.baidu.com/s/1jI1azD8?密碼:4725?
??我也是通過里面郝斌的數(shù)據(jù)結(jié)構(gòu)視頻才把數(shù)據(jù)結(jié)構(gòu)掌握的,盡管我大學數(shù)據(jù)結(jié)構(gòu)課打醬油,但是看這個視頻,只要認真,掌握真是小case!?
??閑話我們也嘮完了,下面進入正題,總結(jié)Java當中常用的集合:?
??首先,提出一個接口Collection,這個接口很多集合都有實現(xiàn)它,而Java常用的集合包括List,Set,以及Map。而List,Set和Map都是接口,其中List接口,Set接口是繼承了Collection接口,而Map接口是沒有繼承Collection接口,原因很簡單,因為List和Set集合一般放的單個對象,Map放的是鍵值對,也就是成對的兩個對象,鍵值對就是可以根據(jù)一個鍵值獲得對應的一個值,因為Collection不具備這種特點,所以Map并沒有繼承Collection。值得一提的是Java的集合持有的并不是對象本身,而是一個指向?qū)ο蟮囊?#xff0c;集合當中放的全部都是引用,如果你現(xiàn)在還不理解這句話,那就暫時不去理解,等你學到一定階段,再回頭來理解理解也是可以的,但是請不要把過多的疑問留到以后,要想成為一名牛的Java程序員,當天的疑問當天來解決,只要你有這個習慣,不管是學習什么,最后你一定會成為很牛的人,寫著寫著又在亂扯,那么繼續(xù)回到正題,根據(jù)前面對集合的幾個接口的描述,所以有如下繼承圖:
?
1.List集合:有序可重復
??有序可重復:順序是按照放入的順序排列的,可重復指的是可以放入一樣的元素?
??實現(xiàn)了接口該接口的集合:ArrayList,LinkedList,Vector?
???[1]ArrayList?
?????底層:使用數(shù)組實現(xiàn)?
?????特點:查找效率高,隨機訪問效率高,增刪效率低,非線程安全的?
????說明:由于ArrayList底層是有數(shù)組實現(xiàn)的,那么也就意味著在內(nèi)存當中是一個有一個連續(xù)的內(nèi)存空間構(gòu)成,學過數(shù)據(jù)結(jié)構(gòu)的肯定知道,因為是這種連續(xù),會讓訪問效率變得非常之高,但也會帶來一個問題,當你往中間插入一個元素,那么插入的位置之后的元素,都要往后移動,如果后面的元素有很多,這顯然會讓效率大大降低,那么刪除呢?也同樣面臨同樣的效率問題,因為當你刪除中間的某個元素,位于這個刪除的元素之后的位置的所有元素都要往前移動,查詢呢?因為隨機訪問效率很高,所以查詢的效率非常可觀。看看下面的ArrayList的添加和刪除:?
?
?
接下來就是代碼部分了,數(shù)據(jù)結(jié)構(gòu)的操作從四個方面著手:增刪改查,以下代碼只是基本的操作,實現(xiàn)List接口的集合具備有很多操作,我只是列舉了一些基本操作,要想詳細了解,請查看API,我這里給你Java API1.6中文版鏈接:http://pan.baidu.com/s/1eSIJ9zc?密碼:wjx1
//生成arrayList實例對象????ArrayList<String>?arrayList?=?new?ArrayList<String>();//ArrayList的添加:??arrayList.add("a");?//在末尾添加元素???arrayList.add("b");??arrayList.add("c");??arrayList.add("d");??arrayList.add("e");??arrayList.add(2,"f");//在指定位置插入元素??//ArrayList的刪除??arrayList.remove(2);//移除下標為2的元素??//ArrayList的修改??arrayList.set(0,"a");//把下標為1的元素修改為元素"a"??//ArrayList的查詢,這里需要遍歷ArrayList??
//普通for語句遍歷??
for(int?i=0;i<arrayList.size();i++){??if(arrayList.get(i).equals("a")){??System.out.println("該集合當中存在a元素,并且位置在第"+(i+1));??}??
}??//foreach語句遍歷??
for(String?str:arrayList){??if(str.equals("a")){??System.out.println("該集合當中存在a元素");//輸出其位置就要另外添加變量了??}??
}????//迭代器方式:??
Iterator<String>?intertor?=?arrayList.iterator();??
while(intertor.hasNext()){??if(intertor.next().equals("a")){??System.out.println("該集合當中存在a元素");?????}??
} ??[2]LinkedList?
?????底層:使用雙向循環(huán)鏈表實現(xiàn)?
?????特點:查找效率低,隨機訪問效率低,增刪效率高,非線程安全的?
????說明:由于LinkedList底層是由雙向循環(huán)鏈表實現(xiàn)的,那么這就意味著,內(nèi)存當中,它存儲的每一個元素的內(nèi)存空間不是連續(xù)的,這給查詢和訪問,帶來了不便,但是也存在著極大的好處,就是增刪效率遠遠高于ArrayList,因為學過數(shù)據(jù)結(jié)構(gòu)的都知道,鏈表的增刪只需要修改指針指向就可以了,不會像數(shù)組那樣每次刪除,都需要元素配合進行移動,LinkedList并不需要每個元素進行移動,光說你肯定是不會理解的,那么看看下面的LinkedList的添加和刪除:????
代碼部分我就不寫了,因為在代碼上LinkedList的增刪改查與ArrayList是一樣的。?
??[3]Vector?
????說明:這個集合和ArrayList相似,但是它具有一些集合都不具有的特點,最大的不同之處,它跟枚舉有關(guān)系。還要很重要的一點,Vector是線程安全,因為是線程安全的,所以效率上比ArrayList要低。這里就不具體介紹Vector了,因為用到的并不多,但也有可能會使用到。詳細了解看Java API。
2.Set集合:無序不可重復
??無序不可重復:無序指的是Set集合的排列順序并不會按照你放入元素的順序來排列,而是通過某些標準進行排列,不可重復指的是Set集合是不允許放入相同的元素,也就是相同的對象,對象相同是怎么判斷的呢?Set集合是通過兩個方法來判斷其元素是否一樣,這兩個方法就是hashCode()方法和equlas()方法,首先,hashCode()方法返回的是一個哈希值,這個哈希值是由對象在內(nèi)存中的地址所形成的,如果兩個對象的哈希值不一樣,那么這兩個對象肯定是不相同的,如果哈希值一樣,那么這還不能肯定這兩個對象是否一樣,還需要通過equlas()方法比較一下兩個對象是否一樣,equals()返回true才能說明這兩個對象是相同的,所以當你想把你自定義的類對象放入此集合,最好重寫一下hashCode()方法和equals()方法來保證Set集合”無序不可重復”的特點。判斷兩個對象是否一樣是通過以下圖片當中的流程,圖片會讓你更加理解。?
?
??[1]HashSet?
?????底層:使用哈希表實現(xiàn)?
?????特點:非線程安全的,放入對象后,其對象的位置與對象本身的hashCode()方法返回的哈希值有關(guān)。判斷重不重復,是通過對象本身的hashCode()方法和equals()方法決定的,所以當你想把你自定義的類對象放入此集合,最好重寫一下hashCode()方法和equals()方法。?
接下來,就是演示如何使用這個HashSet集合了,還是從4個方面著手:增刪改查
//HashSet的操作
//生成HashSet的實例對象HashSet<String>?hashSet?=?new?HashSet<String>();//HashSet的增加hashSet.add("1");hashSet.add("2");hashSet.add("3");hashSet.add("4");hashSet.add("5");//HashSet的刪除hashSet.remove("2");//HashSet的修改//因為HashSet的元素不存在通過下標去訪問,所以修改操作是沒有的//HashSet的查詢//foreach語句方式for(String?str:hashSet){if(str.equals("a")){System.out.println("該集合中存在a元素");}}//迭代器方式:
Iterator<String>?intertor1?=?hashSet.iterator();
while(intertor1.hasNext()){if(intertor1.next().equals("a")){System.out.println("該集合當中存在a元素");???}
} ??[2]TreeSet?
?????底層:使用樹實現(xiàn)?
?????特點:非線程安全的,排序規(guī)則是默認使用元素的自然排序,或者根據(jù)實現(xiàn)Comparable接口(比較器)的compareTo()方法進行排序。判斷重不重復也是通過compareTo()方法來完成的,當compareTo()方法返回值為0時,兩個對象是相同的。所以存入TreeSet集合的對象對應的類一定要實現(xiàn)Comparable接口。?
????代碼我就不寫了,因為TreeSet集合的增刪改查操作基本與HashSet一樣,但是必須詳細說明一下,如果你想把自己定義的類放入TreeSet集合,那么那個自定義類必須支持自然排序,說得明白點,就是一定要實現(xiàn)Comparable接口(比較器接口)。下面寫個例子,比如:需要在TreeSet集合當中放入10個Student對象,實現(xiàn)通過年齡進行排序,然后按照年齡的順序輸出者10個Student對象的信息。分析一下,其實這個例子就是讓你封裝的自定義的類,在運用于TreeSet集合的時候能夠保證其唯一性和某個排序規(guī)則。所以你在封裝你的自定義類的時候一定考慮兩點:?
1.唯一性的判斷:假設(shè)有兩個Student類對象a和Student類對象b,你得保證把a和b對象放入TreeSet集合的時候,a和b是不同的對象,那么憑借什么來判斷呢?假設(shè)Student有name,age屬性,判斷兩個Student對象一樣,那么就是判斷name屬性和age屬性是否一樣,換句話說,當兩個對象一樣的時候,這兩個對象的所有屬性都是相同的。這個判斷需要你的自定義類實現(xiàn)Comparable接口(比較器接口),然后重寫compareTo()方法,當這個方法返回0的時候,意味著被比較的兩個對象是相同的。?
2.排序規(guī)則:TreeSet的排序規(guī)則也是需要自定義類實現(xiàn)Comparable接口(比較器接口),然后重寫compareTo()方法,當這個方法返回正值的時候,意味著前面的對象大于后面的對象,否則,意味著前面的對象小于后面的對象。?
下面是詳細的代碼:
import?java.util.TreeSet;public?class?StudentTreeSetDemo?{public?static?void?main(String[]?args)?{TreeSet<Student>?treeSet?=?new?TreeSet<Student>();treeSet.add(new?Student("a",?1));treeSet.add(new?Student("b",?2));treeSet.add(new?Student("c",?3));treeSet.add(new?Student("d",?5));treeSet.add(new?Student("e",?3));treeSet.add(new?Student("f",?7));//放入相同的treeSet.add(new?Student("d",?5));treeSet.add(new?Student("e",?3));treeSet.add(new?Student("b",?2));for(Student?student:treeSet){student.allMessage();}}}class?Student?implements?Comparable<Student>{
public?String?name;
public?int????age;public?Student(String?name,int?age?)?{this.name?=?name;this.age?=?age;
}public?void?allMessage(){System.out.println("學生名字:"+name+",學生年齡:"+age);
}@Override
public?int?compareTo(Student?o)?{//排序規(guī)則:按照年齡進行排序return?age?-?o.age?!=?0?age?-?o.age:(name.equals(o.name)?0:1);
}} 還要一個需要了解的Set集合,LinkedHashSet集合:?
LinkedHashSet集合跟HashSet一樣是根據(jù)放入的對象的hashCode()方法返回的哈希值來決定元素的存儲位置,但是它同時使用鏈表維護元素的次序。為什么這么做呢?因為這樣做可以讓放入的元素像是以插入順序保存的,換句話說,當遍歷LinkedHashSet集合的時候,LinkedHashSet將會以元素的放入順序來依次訪問的。所以LinkedHashSet在遍歷或者迭代訪問全部元素時,性能方面LinkedHashSet比HashSet好,但是插入時性能就比HashSet差些。
3.Map集合:存儲的是鍵值對
??Map集合存儲的元素是成對出現(xiàn)的,存放的是鍵值對,鍵值是唯一的,但是值可以重復,可以理解為超市里面的存儲箱,一個鑰匙只能打開對應的存儲箱,而存儲箱里面的東西是可以一樣的,這里的鍵就是鑰匙,這里的值就是就是鑰匙對應的存儲箱里面的東西。鍵是唯一的,值可以不唯一。Map的鍵是一個Set集合,只有這樣才可以保證鍵的唯一性,因為Set集合從不放入重復的元素,這就保證了鍵的唯一性。?
??[1]HashMap?
????底層:數(shù)組和鏈表的結(jié)合體(在數(shù)據(jù)結(jié)構(gòu)稱“鏈表散列“) ?
????特點:非線程安全,當你往HashMap中放入鍵值對的時候,如果你放入的鍵是自定義的類,那么其該鍵值對的位置與鍵對象本身的hashCode()方法返回的哈希值有關(guān)。判斷重不重復,是通過鍵對象本身的hashCode()方法和equals()方法決定的,所以當你想把你自定義的類對象通過鍵來放入HashMap集合,最好重寫一下這個自定義類的hashCode()方法和equals()方法。其實Map主要的特點都是通過鍵來完成的,所以你只要封裝好你的自定義類,就可以保證鍵值的唯一性。?
下面來看看代碼,HashMap的增刪改查
???//HashMap的操作??HashMap<String,Integer>?hashMap?=?new?HashMap<String,Integer>();//HashMap的添加hashMap.put("1",?1);hashMap.put("2",?2);hashMap.put("3",?3);hashMap.put("4",?4);//HashMap的刪除hashMap.remove("2");//移除鍵值為"2"的元素//HashMap的修改hashMap.put("1",?11);//將鍵值為"1"的元素的鍵值覆蓋為"11",修改其實就覆蓋//HashMap的查詢,這里需要遍歷HashMap//1.通過遍歷鍵的Set集合來遍歷整個Map集合System.out.println("foreach遍歷");for(String?str:hashMap.keySet()){System.out.println(str+":"+hashMap.get(str));}System.out.println("迭代器遍歷");Iterator<String>?intertor?=?hashMap.keySet().iterator();while(intertor.hasNext()){String?key?=?intertor.next();System.out.println(key+":"+hashMap.get(key));}//2.使用Map集合的關(guān)系遍歷System.out.println("Map關(guān)系遍歷");for(Map.Entry<String,?Integer>?entry:hashMap.entrySet()){System.out.println(entry.getKey()+":"+entry.getValue());} ??[2]TreeMap?
????底層:使用樹實現(xiàn)?
????特點:非線程安全,鍵是TreeSet集合,排序規(guī)則是默認使用元素的自然排序,或者根據(jù)實現(xiàn)的Comparable接口(比較器)的compareTo()方法進行排序。判斷重不重復也是通過compareTo()方法來完成的,當compareTo()方法返回值為0時,兩個對象是相同的。所以保證唯一性,只需要讓鍵對應的類實現(xiàn)Comparable接口(比較器),并且實現(xiàn)compareTo()方法。所以存入TreeMap集合作為鍵的對象對應的類一定要實現(xiàn)Comparable接口。 而跟TreeSet一樣,放入后的排序,以及鍵的唯一性都是通過compareTo()方法完成的。所以如何讓自定義的類通過鍵值放入TreeMap集合,并且保證唯一性,和按照一定規(guī)則排序,只需要這個自定義類實現(xiàn)Comparable接口(比較器),實現(xiàn)compareTo()方法即可。例子我就不舉了,其實和TreeSet的那個例子基本一樣。
??[3]HashTable?
????底層:使用哈希表實現(xiàn)的?
????特點:線程安全,基本特點和用法和HashMap相似,性能上稍微差于HashMap,因為HashTable是線程安全的。這個集合我就不詳細說明了,基本和HashMap類似,唯一不同的是它是線程安全的。
??還有一個集合需要了解一下,LinkedHashMap,這個我想不用我說你也應該知道了,其實和前面說的LinkedHashSet差不多。可以結(jié)合前面的LinkedHashSet來分析一下LinkedHashMap,我想這對于你來說不難。
轉(zhuǎn)載于:https://www.cnblogs.com/dhshappycodinglife/p/11047766.html
總結(jié)
以上是生活随笔為你收集整理的[转]Java中常用的集合—初学者的你不可错过的精编整理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 护肤专业人士或经验多的进~~23岁就需要
- 下一篇: 菜鸟