一. ArrayList嵌套
1.定義
在集合中存放集合,和二維數(shù)組類(lèi)似
2.演示
public static void main(String[] args) {
? ? //集合中的元素還是集合
? ? ArrayList<ArrayList<Student>> school = new ArrayList<>();
? ? ArrayList<Student> clas1 = new ArrayList<>();
? ? clas1.add(new Student("小紅",18));
? ? clas1.add(new Student("小明",20));
? ? school.add(clas1);
? ? ArrayList<Student> clas2 = new ArrayList<>();
? ? clas2.add(new Student("小張",18));
? ? clas2.add(new Student("小李",20));
? ? school.add(clas2);
? ? ArrayList<Student> clas3 = new ArrayList<>();
? ? clas3.add(new Student("tom",18));
? ? clas3.add(new Student("jack",20));
? ? school.add(clas3);
? ? System.out.println(school);
}
二. Set集合
1.定義
Set詞義:數(shù)學(xué)中集合的概念。也是Collection的子接口。
Set作為Collection集合的子接口猾普,沒(méi)有新增的功能次舌。但是有自己的存儲(chǔ)特點(diǎn)。
Set集合存數(shù)的元素是無(wú)序的, 而且不允許儲(chǔ)存重復(fù)的元素, 每當(dāng)有新的元素存入的時(shí)候,Set集合會(huì)先去過(guò)濾, 如果發(fā)現(xiàn)和集合中現(xiàn)有元素出現(xiàn)重復(fù), 就不在允許添加
2.應(yīng)用場(chǎng)景
當(dāng)我們不想讓集合中出現(xiàn)重復(fù)的元素時(shí),使用Set集合
當(dāng)我們需要排除重復(fù)數(shù)據(jù)時(shí),使用Set集合
3.演示
public static void main(String[] args) {
? ? //集合中的元素還是集合
? ? HashSet<Student> s = new HashSet<>();
? ? Student student = new Student("小紅",18);
? ? Student student2 = new Student("小紅",18);
? ? s.add(student);
? ? s.add(student2);
? ? Iterator<Student> it = s.iterator();
? ? while(it.hasNext()) {
? ? ? ? Student student3=it.next();
? ? ? ? System.out.println(student3);
? ? }
}
三. HashSet
1.定義
Set接口的一個(gè)具體的實(shí)現(xiàn)類(lèi)约素。
底層是由哈希表實(shí)現(xiàn)。它不保證迭代的順序。特別是不保證順序一直不變硅急。
HashSet集合中的元素是通過(guò)hash值來(lái)比較是否相同
集合通過(guò)元素的hashCode和equals方法來(lái)比較兩個(gè)元素是否相同, 不同就存入, 相同不存入
元素存入的位置未知,和存入的順序無(wú)關(guān)
2.存儲(chǔ)原理
HashSet最后還是存入數(shù)組中, 只是根據(jù)元素的Hash值來(lái)確定存入的角標(biāo)位置
元素的hash值 ^ (元素的hash值 >>> 16) & (數(shù)組的長(zhǎng)度-1)
HashSet中不是直接存入我們給定的元素, 而是用集合中的一個(gè)內(nèi)部類(lèi)封裝我們存入的元素,所以當(dāng)我們存入null的時(shí)候,不會(huì)因?yàn)楹蛿?shù)組中角標(biāo)位上默認(rèn)值null起沖突
如果兩個(gè)不同的元素根據(jù)不同的Hash值計(jì)算出了同一個(gè)角標(biāo)值,那么都能存進(jìn)去
3.構(gòu)造方法
HashSet()? ? 構(gòu)造出一個(gè)新的集合, 底層數(shù)組默認(rèn)的初始容量是16(擴(kuò)容一倍),加載因子是0.75
加載因子: 集合中的數(shù)組可用的
角標(biāo)值得可選范圍越小,計(jì)算出重復(fù)角標(biāo)值得概率就越高
HashSet(Collection<? extends E> c) 構(gòu)造一個(gè)包含指定collection中元素的新set?
4.常用方法
boolean add( E e)? ? 如果此set集合中尚未包含指定元素,則添加指定元素
boolean remove(Object o)? ? 移除某個(gè)元素 []
int size()? ? 獲取集合的長(zhǎng)度
5.重點(diǎn)重點(diǎn)重點(diǎn)!<阉臁营袜!HashSet集合去重的流程:
step1:先獲取對(duì)象的hashCode,對(duì)象的哈希值不同丑罪,直接存儲(chǔ)到HashSet容器中荚板。
step2:如果哈希值相同,調(diào)用equals()比較吩屹。
true:認(rèn)為是相同的元素跪另,不存儲(chǔ)
false:不同的元素,存儲(chǔ)
原則:hashCode()和equals()的原則:
重寫(xiě)hashCode()的規(guī)則:自己生成hashCode值煤搜。公式
對(duì)象相同:屬性值相同免绿。那么哈希碼必須相同。
對(duì)象不同:屬性值不同擦盾。哈希碼也可能相同嘲驾。
重寫(xiě)equals()的原則:"權(quán)威的"
如果兩個(gè)對(duì)象的屬性值相同淌哟,認(rèn)為是相同的對(duì)象,返回true辽故。
如果兩個(gè)對(duì)象的屬性值有不同徒仓,就不是相同的對(duì)象,返回false誊垢。
結(jié)論:如果想使用HashSet集合掉弛,那么必須同時(shí)重寫(xiě)對(duì)象的hashCode()和equals()這兩個(gè)方法。
重寫(xiě)的規(guī)則:
hashCode()
對(duì)象相同彤枢,屬性值相同狰晚。哈希碼必須相同。
對(duì)象不同缴啡,屬性值不同壁晒。哈希碼可能相同。
equals()
對(duì)象相同:屬性值相同业栅。必須true秒咐。
對(duì)象不同:屬性值不同。必須false碘裕。
6.演示
需求: 去除ArrayList集合中的重復(fù)元素
public static void main(String[] args) {
? ? ArrayList<String> al = new ArrayList<>();
? ? al.add("a");
? ? al.add("s");
? ? al.add("x");
? ? al.add("a");
? ? al.add("s");
? ? HashSet<String> hs = new HashSet<>(al);
? ? System.out.println(hs);
}
7.測(cè)試題
需求: 創(chuàng)建Student類(lèi), 定義name和age屬性, 創(chuàng)建多個(gè)對(duì)象(有屬性重復(fù)的對(duì)象)存入ArrayList集合中, 然后對(duì)集合中的元素去重
四. HashSet集合中元素保證唯一性
1.原理解析
HashMap是通過(guò)調(diào)用元素的hashCode方法來(lái)比較兩個(gè)元素是否形同的,所有如果要保證引用數(shù)據(jù)類(lèi)型邏輯上的唯一性,就必須重寫(xiě)hashCode方法和equals方法
2.演示
public int hashCode() {
????final int prime = 31;
????int result = 1;
????result = prime * result + age;
????result = prime * result + ((name == null) ? 0 : name.hashCode());
????return result;
}
prime = 31 的原因
????別人選的, 沒(méi)有原因
????是質(zhì)數(shù), 和別的值計(jì)算得出的數(shù)重復(fù)的概率低
????大小適中, 不會(huì)出現(xiàn)太大導(dǎo)致結(jié)果無(wú)法使用的問(wèn)題
????便于計(jì)算 2<<5 -1
3.引用數(shù)據(jù)類(lèi)型除重
重寫(xiě)hashCode和equals方法,自定義比較內(nèi)容
4.測(cè)試題
需求: 編寫(xiě)程序, 獲取10個(gè)1到20的隨機(jī)數(shù), 要求隨機(jī)數(shù)不能重復(fù), 打印結(jié)果
public static void main(String[] args) {
????Random random = new Random();
????HashSet<Integer> hashSet = new HashSet<>();
????while(hashSet.size()<10){
????????int num = random.nextInt(20)+1;
????????hashSet.add(num);
????}
????System.out.println(hashSet);
}
5.測(cè)試題
需求: 從鍵盤(pán)錄入一行數(shù)據(jù), 去掉其中重復(fù)的字符,打印結(jié)果
6.測(cè)試題
產(chǎn)生10個(gè)隨機(jī)的字符串, 要求不能重復(fù)(字符串中的字符取值在 'a' 到 'z' , 'A' 到 'Z' ,'0' 到 '9'),字符串的長(zhǎng)度1-20
五. LinkedHashSet
1.定義
兼顧了linked的有序性和HashSet的元素唯一性
2.演示
六. TreeSet集合
1.定義
TreeSet是一種順序的集合, 記住, 這里的順序是指集合中的元素有順序, 她是通過(guò)比較元素的大小來(lái)存放的, 大的存右邊,小的存左邊
默認(rèn)的規(guī)則:Comparable接口携取,定義排序的規(guī)則。
存入的元素必須實(shí)現(xiàn)Comparable接口,并且重寫(xiě)comparTo方法(注:重寫(xiě)的方法應(yīng)在該元素的類(lèi)中帮孔,而不是測(cè)試類(lèi)中重寫(xiě))
java.lang.Comparable接口的用途:強(qiáng)行對(duì)實(shí)現(xiàn)類(lèi)的對(duì)象進(jìn)行排序雷滋。
compareTo()-->此方法用于排序,返回值int類(lèi)型
o1.compareTo(o2)-->int
????正數(shù):o1 > o2文兢,將o1排在o2的后面晤斩。
????負(fù)數(shù):o1 < o2,將o1排在o2的前面姆坚。
????零:認(rèn)為o1和o2相同澳泵,不存儲(chǔ)了。
最后存入的元素會(huì)形成一個(gè)樹(shù)狀結(jié)構(gòu)
擴(kuò)展內(nèi)容:
紅黑樹(shù)--->平衡二叉樹(shù)--->二叉樹(shù)--->樹(shù)
想了解平衡二叉樹(shù)兼呵,可以參照此網(wǎng)址:https://baijiahao.baidu.com/s?id=1651427207567199156&wfr=spider&for=pc
2.構(gòu)造方法
TreeSet()? ? 構(gòu)造一個(gè)新的空set, 該set根據(jù)其元素的自然順序進(jìn)行排序
TreeSet(Comparator <? super E> comparator)? 構(gòu)建一個(gè)空的TreeSet, 他根據(jù)指定比較器進(jìn)行排序
3.常用方法
add(E e)? ? 將指定元素添加到此set
first()? ? 返回此set中當(dāng)前第一元素
last()? ? 返回此set中當(dāng)前最后一個(gè)元素
floor()? ? 返回此set中小于等于給定元素的最大元素,不存在則返回null
higher()? ? 返回此set中嚴(yán)格大于給定元素的最小元素,不存在則返回null
5.添加原理
TreeSet會(huì)將第一個(gè)添加的元素作為中點(diǎn), 以后添加的元素會(huì)先跟中點(diǎn)進(jìn)行比較, 如果大于就接著跟所比較元素的右邊的元素接著比較,如果小于就接著跟所比較元素左邊的元素接著比較, 直到無(wú)法找到可比較的元素,就會(huì)將新添加的這個(gè)元素放到當(dāng)前位置
6.Comparable接口(默認(rèn)的比較器)
java.lang.Comparable接口
java.lang.Comparable接口的用途:強(qiáng)行對(duì)實(shí)現(xiàn)類(lèi)的對(duì)象進(jìn)行排序兔辅。
僅有唯一的一個(gè)方法:compareTo()-->此方法用于排序,返回值int類(lèi)型類(lèi)型
o1.compareTo(o2)-->int ?? (從小到大排序)
????正數(shù):o1 > o2击喂,將o1排在o2的后面维苔。
????負(fù)數(shù):o1 < o2,將o1排在o2的前面懂昂。
????零:認(rèn)為o1和o2相同蕉鸳,不存儲(chǔ)了。
默認(rèn)的TreeSet集合忍法,使用的是Comparable接口潮尝,來(lái)給對(duì)象進(jìn)行排序。以及去重饿序。
所有存入的元素在比較的時(shí)候,如果集合沒(méi)有比較器, 就會(huì)將元素本身轉(zhuǎn)成Comparator類(lèi)型并調(diào)用comparTo方法進(jìn)行比較, 所以我們必須實(shí)現(xiàn)Comparato接口,并重寫(xiě)comparTo方法
7.Comparator比較器(自定義的比較器)
這是一個(gè)接口, 定義了一個(gè)compare抽象方法
compare方法可以對(duì)兩個(gè)元素進(jìn)行比較
????如果方法返回一個(gè)小于0的數(shù),表示參數(shù)1小于參數(shù)2
????如果返回 0 ,表示參數(shù)1等于參數(shù)2
????如果返回一個(gè)大于0的數(shù), 表示參數(shù)1大于參數(shù)2
演示
8.注意事項(xiàng)
TreeSet集合的存儲(chǔ)原理限定了必須要對(duì)存入的元素進(jìn)行比較
要么存入的元素自身實(shí)現(xiàn)Comparable接口, 要么提供外部的實(shí)現(xiàn)了Comparator接口的比較器, 否則程序運(yùn)行就會(huì)報(bào)錯(cuò)
注意點(diǎn):創(chuàng)建一個(gè)TreeSet集合勉失,到底使用哪個(gè)比較器?Comparable乱凿?Comparator?
無(wú)參構(gòu)造:new TreeSet();-->使用默認(rèn)的比較器:Comparable
有參構(gòu)造:new TreeSet(Comparator)-->使用自定義的比較器:Comparator
9.測(cè)試題
需求: 鍵盤(pán)錄入5個(gè)學(xué)生信息(姓名,語(yǔ)文成績(jī),數(shù)學(xué)成績(jī),英語(yǔ)成績(jī)),按照總分從高到低輸出到控制臺(tái)
演示
10.LinkedHashSet集合
回憶:HashSet存儲(chǔ)特點(diǎn)咽弦?1徒蟆、無(wú)序。2型型、去重
HashSet存儲(chǔ)數(shù)據(jù)段审,記錄存儲(chǔ)的順序。
Set集合的另一個(gè)實(shí)現(xiàn)類(lèi):LinkedHashSet
存儲(chǔ)原理同HashSet相同闹蒜,但是外層套了一個(gè)鏈表結(jié)構(gòu)寺枉。用于記錄存儲(chǔ)的順序。
七. 超級(jí)for
1.定義
????Iterator的簡(jiǎn)寫(xiě)形式
????簡(jiǎn)化數(shù)組和Collection集合的遍歷
2.格式
3.演示
4.三種迭代方式的刪除
????普通for循環(huán),可以刪除,但是需要角標(biāo)
????迭代器,可以刪除,但是必須使用迭代器自身的remove方法,否則會(huì)出現(xiàn)并發(fā)修改異常
????超級(jí)for循環(huán)不能刪除
八. Collections工具類(lèi)的使用
1.定義
????一個(gè)用于操作Collection集合工具類(lèi)
2.常用方法
????sort(List<T> list) 根據(jù)元素的自然順序排序
????swap(List<T> list , int i , int j) 交換集合中兩個(gè)角標(biāo)位上的值
????reverse(List<?> list ) 反轉(zhuǎn)集合中的元素的順序
????replaceAll(List<T> list, T oldVal, T newVal) 替換
3.演示
總結(jié)
1.Set集合:特點(diǎn)绷落,去重姥闪,無(wú)序。
2.HashSet:
????去重效率高, 尤其是在大數(shù)據(jù)量下砌烁,散列存儲(chǔ)筐喳。不講究存儲(chǔ)順序。
????調(diào)用元素的hashCode和equals方法來(lái)比較是否相同
3.TreeSet:
? ? 去重, 元素有序(對(duì)存入的元素進(jìn)行排序)
????要求存入的元素必須具備比較的能力或者提供第三方的比較器
????元素具備比較的能力 : 元素實(shí)現(xiàn)comperable接口, 重寫(xiě)comparTo方法
????第三方比較器: 定義類(lèi),實(shí)現(xiàn)Compartor接口, 從寫(xiě)? compare方法
4.LinkedHashSet
????即有序(集合有序), 又能去重
????效率不高
5.超級(jí)for
????迭代器的簡(jiǎn)寫(xiě)形式
????優(yōu)點(diǎn): 格式簡(jiǎn)單
????缺點(diǎn): 無(wú)法進(jìn)行刪除操作
6.Collections
????一個(gè)用來(lái)操作List集合的工具類(lèi)