摘要:如果你知道用集合,就用。在集合中常見的數據結構底層數據結構是數組,查詢快,增刪慢底層數據結構是鏈表,查詢慢,增刪快底層數據結構是哈希表。依賴兩個方法和底層數據結構是二叉樹。
第三階段 JAVA常見對象的學習 集合框架——Set接口
List集合的特點是有序的,可重復的,是不是存在這一種無序,且能保證元素唯一的集合呢?(HashSet )這就涉及到我們今天所要講的Set集合(一) 概述及功能 (1) 概述Set可以理解為行為不同的Collection
Collection
List —— 有序(存儲順序和取出順序一致),可重復
Set—— 無序(存儲順序和取出順序不一致),唯一
我們首先要清楚有序無序,到底是什么意思?
集合所說的序,是指元素存入集合的順序,當元素存儲順序和取出順序一致時就是有序,否則就是無序。
我們一般說的無序是指HashSet,它既不能保證存儲和取出順序一致,更不能保證自然順序(a-z),而TreeSet 是可以實現自然順序的。(HashSet的有無序問題可是個大問題,下一篇專篇講解)
(2) 功能//添加功能 boolean add(E e):如果指定的元素不存在,則將其指定的元素添加(可選操作) boolean addAll(Collection extends E> c):將指定集合中的所有元素添加到此集合 //刪除功能 void clear():移除集合中的所有元素 boolean remove(Object o):從集合中移除指定的元素 boolean removeAll(Collection> c):從集合中移除一個指定的集合元素(有一個就返回true) //長度功能 int size(); //判斷功能 boolean isEmpty():判斷集合是否為空 boolean contains(Object o):判斷集合中是否包含指定元素 boolean containsAll(Collection> c):判斷集合中是否包含指定的一個集合中的元素 boolean retainAll(Collection> c):僅保留該集合中包含在指定集合中的元素 //獲取Set集合的迭代器: Iteratoriterator(); //把集合轉換成數組 Object[] toArray():返回一個包含此集合中所有元素的數組 T[] toArray(T[] a):同上,返回的數組的運行時類型是指定數組的運行時類型
//判斷元素是否重復,為子類提高重寫方法 boolean equals(Object o):將指定的對象與此集合進行比較以實現相等 int hashCode();:返回此集合的哈希碼值
Set集合中的方法用法并不難,可以參照前面Collection、List集合的講解,對照學習,我們重點講解Set中一些重要的特點。
(二) HashSet一句話記住它:一種沒有重復元素的無序集合
我們先說說無序是怎么回事,HashSet 它不保證 set 的迭代順序,特別是它不保證該順序恒久不變,也就是說它的存儲順序和取出順序不一致,雖然說它無序,但是,作為集合來說,它肯定有它自己的存儲順序,而你的順序恰好和它的存儲順序一致,這代表不了有序。下一篇專篇講解這一問題!
無序問題由于篇幅較長,我們先放到另一邊
我們先來思考一下,HashSet是如何保證不重復的呢?
通過查看HashSet中add方法的源碼
// HashSet 源碼節選-JKD8 public boolean add(E e) { return map.put(e, PRESENT)==null; }
我們可以看到HashSet中add方法所調用的是HashMap中的put方法,我們定位過去
由于解釋篇幅較長,直接給出結論,具體源碼解釋在HashMap源碼分析中具體講解
這個方法底層主要依賴 兩個方法:hashCode()和equals()。
步驟:
HashSet方法調用add方法時,調用hashCode(),得到一個哈希值,判斷哈希值是否相同。
相同:執行equals()方法
? 返回true:說明元素重復,就不添加
? 返回false:說明元素不重復,就添加到集合
不同:就直接把元素添加到集合
現在大家可能想問一句,只使用hashCode()來判斷是否重復可以嗎?答案是否定的
我們給出這樣一句話:
對象相等則hashCode一定相等,hashCode相等對象未必相等,只有equals返回true,hashCode才相等
如果類沒有重寫這兩個方法,默認使用的Object()。一般來說不會相同。
而String類重寫了hashCode()和equals()方法,所以,它就可以把內容相同的字符串去掉。只留下一個。
對于String 類型來說,不用重寫 hashCode()方法和equals()方法都可以保證元素的唯一性,但是如果不是Stirng,而是其它自定義的對象就要重寫這兩個方法才能保證元素的唯一性。
(三) TreeSet 概述:TreeSet:底層是二叉樹結構(紅黑樹是一種自平衡的二叉樹)
如何存儲那么這一種結構又是如何存儲元素的呢?(我們將上圖中圓圈稱為節點)
第一個元素存儲的時候,直接作為根節點存儲
第二個元素開始,每個元素從根節點開始比較
若大 則作為右孩子
若小 則作為左孩子
相等 則不作處理
我們來舉一個例子看看:
import java.util.Set; import java.util.TreeSet; public class TreeSetDemo { public static void main(String[] args) { Setts = new TreeSet (); ts.add(20); ts.add(18); ts.add(23); ts.add(22); ts.add(17); ts.add(24); ts.add(19); ts.add(18); ts.add(24); for (Integer i : ts) { System.out.print(i + " "); } } } //運行結果 17 18 19 20 22 23 24
我們使用圖片來解釋一下上面的代碼
我們將第一個數字20 作為根節點存放,第二個數字18比20小所以放在左邊 23大放在右邊
例如22這個數字是如何放到如圖的位置呢?
首先22先和20比較是大的所以放到右邊,接著繼續和23進行比較是小的,所以放到23的左邊,接下來同理
我們看到運行結果,很神奇的是按照順序輸出的,這也正符合了我們一開始給出的結論:TreeSet 是可以實現自然順序的
如何取出那么TreeSet中元素是如何取出來的呢?
從根節點開始,按照左,中,右的原則依次取出元素即可
分析:我們的根節點是20,所以先看左邊也就是18,但是下面還有子節點,我們繼續看左邊所以第一個數字就是17,然后再看中和右也就是18和19,這時候根節點的左邊也就全部看完了,所以接著就是中間的根節點20,右邊同理。
如何存儲自定義對象我們設定一種場景,存儲學生類中的學生對象,并且按照年齡從小到大排序(自然排序)
當滿足所有成員變量的值都相同的時候即為同一個元素
注意:如果一個類的元素要想能夠進行自然排序,就必須實現自然排序接口(關鍵)
public class Student implements Comparable{ private String name; private int age; public Student() { } public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Student{" + "name="" + name + """ + ", age=" + age + "}"; } @Override public int compareTo(Student s) { //按照年齡排序 //年齡相同的時候,去看姓名是否也相同 //String 默認實現了Comparavle接口,所以可以直接使用字符串的compareTo方法 int num = this.age - s.age; int num2 = num == 0 ? this.name.compareTo(s.name) : num; return num2; } }
import java.util.Set; import java.util.TreeSet; public class StudentDemo { public static void main(String[] args) { Setts = new TreeSet (); Student s1 = new Student("張三",27); Student s2 = new Student("李四",16); Student s3 = new Student("王五",40); Student s4 = new Student("馬六",40); Student s5 = new Student("馬六",40); ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); for (Student s : ts){ System.out.println(s); } } } //運行結果 Student{name="李四", age=16} Student{name="張三", age=27} Student{name="王五", age=40} Student{name="馬六", age=40}
我們可以專門定義了一個類MyComparator,其實也可以省略這一個類,直接在TreeSetDemo測試類中定義一個匿名內部類
package cn.bwh_04_TreeSet; import java.util.Comparator; import java.util.Set; import java.util.TreeSet; public class StudentDemo2 { public static void main(String[] args) { SetCollection 集合總結ts = new TreeSet (new Comparator () { @Override public int compare(Student2 s1, Student2 s2) { //姓名長度 int num = s1.getName().length() - s2.getName().length(); //姓名內容 int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num; //年齡 int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2; return num3; } }); Student2 s1 = new Student2("張三", 27); Student2 s2 = new Student2("李四", 16); Student2 s3 = new Student2("王五", 40); Student2 s4 = new Student2("馬六", 40); Student2 s5 = new Student2("馬六", 40); ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); for (Student2 s : ts) { System.out.println(s); } } }
Collection集合應用時的選擇
是否唯一
唯一:Set
需要排序:TreeSet
不需要排序:HashSet
如果你知道是Set,但是不知道是哪個Set,就用HashSet。
不唯一:List
需要安全:Vector
不需要安全:ArrayList或者LinkedList
查詢多:ArrayList
增刪多:LinkedList
如果三原則
如果你知道是List,但是不知道是哪個List,就用ArrayList。
如果你知道是Collection集合,但是不知道使用誰,就用ArrayList。
如果你知道用集合,就用ArrayList。
在集合中常見的數據結構
ArrayXxx:底層數據結構是數組,查詢快,增刪慢
LinkedXxx:底層數據結構是鏈表,查詢慢,增刪快
HashXxx:底層數據結構是哈希表。依賴兩個方法:hashCode()和equals()
TreeXxx:底層數據結構是二叉樹。兩種方式排序:自然排序和比較器排序
結尾:如果內容中有什么不足,或者錯誤的地方,歡迎大家給我留言提出意見, 蟹蟹大家 !^_^
如果能幫到你的話,那就來關注我吧!(系列文章均會在公眾號第一時間更新)
在這里的我們素不相識,卻都在為了自己的夢而努力 ?一個堅持推送原創Java技術的公眾號:理想二旬不止
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/75195.html
集合接口 核心集合接口封裝了不同類型的集合,如下圖所示,這些接口允許獨立于其表示的細節來操縱集合,核心集合接口是Java集合框架的基礎,如下圖所示,核心集合接口形成層次結構。 showImg(https://segmentfault.com/img/bVbntJW?w=402&h=146); Set是一種特殊的Collection,SortedSet是一種特殊的Set,依此類推,另請注意,層次結構...
摘要:第三階段常見對象的學習集合框架集合在實際需求中,我們常常會遇到這樣的問題,在諸多的數據中,通過其編號來尋找某一些信息,從而進行查看或者修改,例如通過學號查詢學生信息。面試題和的區別是單列集合的頂層接口,有子接口和。 第三階段 JAVA常見對象的學習 集合框架——Map集合 showImg(https://segmentfault.com/img/remote/1460000019683...
摘要:接口下面包含等。但是接口并沒有繼承接口,因此無法迭代。分離出接口是迭代器模式。但是接口又提供了接口以后將轉換成集合來迭代。的增強循環也只適用于那些繼承了接口的。 Iterator接口是Collection接口的父接口。Collection接口下面包含List,Set,Queue等。 Map接口與Collection接口同級。但是Map接口并沒有繼承Iterator接口,因此無法迭代。 ...
摘要:集合工具包是在包中,實現了數據結構數組棧鏈表隊列映射和集合。集合主要可以劃分為個部分列表集合映射工具類迭代器枚舉類和。集合的框架圖如下圖片來源集合頂層接口主要有和。和都是集合遍歷相關接口,是特有的遍歷工具接口 Java集合工具包是在java.util.*包中,實現了數據結構:數組、棧、鏈表、隊列、映射和集合。Java集合主要可以劃分為4個部分:List列表、Set集合、Map映射、工具...
摘要:說到復盤基礎,并不是所有的都會復盤,沒那個時間更沒那個必要。比如,一些基礎的語法以及條件語句,極度簡單。思前想后,我覺得整個計劃應該從集合開始,而復盤的方式就是讀源碼。通常,隊列不允許隨機訪問隊列中的元素。 ?showImg(https://segmentfault.com/img/remote/1460000020029737?w=1080&h=711); 老讀者都知道,我是自學轉行...
閱讀 3172·2021-11-23 09:51
閱讀 685·2021-10-14 09:43
閱讀 3207·2021-09-06 15:00
閱讀 2410·2019-08-30 15:54
閱讀 2563·2019-08-30 13:58
閱讀 1850·2019-08-29 13:18
閱讀 1379·2019-08-27 10:58
閱讀 513·2019-08-27 10:53