Java进阶(七)Set系列集合、Map集合体系
七.Set系列集合、Map集合體系
需要學(xué)會(huì)什么?
- Set系列集合的特點(diǎn):Set系列集合的特點(diǎn)和底層原理。
- 集合工具類Collections:快速的對(duì)集合進(jìn)行元素的添加、排序等操作。
- 綜合案例:把Collection家族的集合應(yīng)用起來解決一些問題。
- Map集合體系:Map體系的集合能解決什么問題,各自的特點(diǎn)是什么樣的。
- 集合的嵌套:開發(fā)中集合中的元素可能又是一種集合形式,這種方式很常見,需要認(rèn)識(shí),并學(xué)會(huì)對(duì)其進(jìn)行處理。
1.Set系列集合
a.Set系列集合概述
#mermaid-svg-npxcx4J1OnMbxBc4 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-npxcx4J1OnMbxBc4 .error-icon{fill:#552222;}#mermaid-svg-npxcx4J1OnMbxBc4 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-npxcx4J1OnMbxBc4 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-npxcx4J1OnMbxBc4 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-npxcx4J1OnMbxBc4 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-npxcx4J1OnMbxBc4 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-npxcx4J1OnMbxBc4 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-npxcx4J1OnMbxBc4 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-npxcx4J1OnMbxBc4 .marker.cross{stroke:#333333;}#mermaid-svg-npxcx4J1OnMbxBc4 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-npxcx4J1OnMbxBc4 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-npxcx4J1OnMbxBc4 .cluster-label text{fill:#333;}#mermaid-svg-npxcx4J1OnMbxBc4 .cluster-label span{color:#333;}#mermaid-svg-npxcx4J1OnMbxBc4 .label text,#mermaid-svg-npxcx4J1OnMbxBc4 span{fill:#333;color:#333;}#mermaid-svg-npxcx4J1OnMbxBc4 .node rect,#mermaid-svg-npxcx4J1OnMbxBc4 .node circle,#mermaid-svg-npxcx4J1OnMbxBc4 .node ellipse,#mermaid-svg-npxcx4J1OnMbxBc4 .node polygon,#mermaid-svg-npxcx4J1OnMbxBc4 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-npxcx4J1OnMbxBc4 .node .label{text-align:center;}#mermaid-svg-npxcx4J1OnMbxBc4 .node.clickable{cursor:pointer;}#mermaid-svg-npxcx4J1OnMbxBc4 .arrowheadPath{fill:#333333;}#mermaid-svg-npxcx4J1OnMbxBc4 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-npxcx4J1OnMbxBc4 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-npxcx4J1OnMbxBc4 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-npxcx4J1OnMbxBc4 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-npxcx4J1OnMbxBc4 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-npxcx4J1OnMbxBc4 .cluster text{fill:#333;}#mermaid-svg-npxcx4J1OnMbxBc4 .cluster span{color:#333;}#mermaid-svg-npxcx4J1OnMbxBc4 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-npxcx4J1OnMbxBc4 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Collection 接口 List 接口 Set 接口 ArrayList 實(shí)現(xiàn)類 LinkedList 實(shí)現(xiàn)類 HashSet 實(shí)現(xiàn)類 LinkedHashSet 實(shí)現(xiàn)類 TreeSet 實(shí)現(xiàn)類Set系列集合特點(diǎn):
- 無序:存取順序不一致。
- 不重復(fù):可以去去除重復(fù)。
- 無索引:沒有帶索引的方法,所以不能使用普通for循環(huán)遍歷,也不能通過索引來獲取元素。
Set集合實(shí)現(xiàn)類特點(diǎn):
- HashSet:無序、不重復(fù)、無索引。
- LinkedHashSet:有序、不重復(fù)、無索引。
- TreeSet:排序、不重復(fù)、無索引。
Set集合的功能基本與Collection的API一致。
Test.java
import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Set;public class Test {public static void main(String[] args) {// Set系列集合的特點(diǎn):HashSet LinkedHashSet TreeSet// 經(jīng)典代碼 多態(tài)寫法 無序不重復(fù) 無索引Set<String> set = new HashSet<>();set.add("SQL");set.add("SQL");set.add("Java");set.add("Java");set.add("Python");set.add("Python");// [Java, Python, SQL]System.out.println(set);// 有序 不重復(fù) 無索引Set<String> set1 = new LinkedHashSet<>();set.add("Java");set.add("Java");set.add("Python");set.add("Python");set.add("SQL");set.add("SQL");// [Java, Python, SQL]System.out.println(set);} }總結(jié):
- 無序、不沖股份、無索引。
- HashSet無序、不重復(fù)、無索引。
- LinkedHashSet有序、不重復(fù)、無索引。
- TreeSet可排序、不重復(fù)、無索引。
b.HashSet元素?zé)o序的底層原理:哈希表
HashSet底層原理:
- HashSet集合底層采取哈希表存儲(chǔ)的數(shù)據(jù)。
- 哈希表是一種對(duì)于增刪改查數(shù)據(jù)性能都較好的結(jié)構(gòu)。
哈希表的組成:
- JDK8之前的,底層使用數(shù)組+鏈表組成。
- JDK8開始后,底層采用數(shù)組+鏈表+紅黑樹組成。
在了解哈希表之前需要先理解哈希值的概念。
哈希值:
- 是JDK根據(jù)對(duì)象的地址,按照某種規(guī)則算出來的int類型的數(shù)值。
Object類的API:
- public int hashCode():返回對(duì)象的哈希值。
對(duì)象的哈希值特點(diǎn):
- 同一個(gè)對(duì)象多次調(diào)用hashCode()方法返回的哈希值是相同的。
- 默認(rèn)情況下,不同對(duì)象的哈希值是不同的。
Test.java
public class Test {public static void main(String[] args) {// 目標(biāo):學(xué)會(huì)獲取對(duì)象的哈希值String name = "Marx";// 2390778System.out.println(name.hashCode());// 2390778System.out.println(name.hashCode());String name1 = "Linus";// 73425103System.out.println(name1.hashCode());// 73425103System.out.println(name1.hashCode());} }HashSet1.7版本原理解析:數(shù)組+鏈表+(結(jié)合哈希算法)
- JDK7中新元素占老元素位置,指向老元素。
- JDK8中新元素掛在老元素下面。
結(jié)論:哈希表是一種對(duì)于增刪改查數(shù)據(jù)性能都較好的結(jié)構(gòu)。
HashSet1.7版本原理解析:數(shù)組-鏈表-(結(jié)合哈希算法)
HashSet1.8版本原理解析:數(shù)組+鏈表+紅黑樹+(結(jié)合哈希算法)
- 底層結(jié)構(gòu):哈希表(數(shù)組、鏈表、紅黑樹的結(jié)合體)。
- 當(dāng)掛在元素下面的數(shù)據(jù)過多時(shí),查詢性能降低,從JDK8開始后,當(dāng)鏈表長(zhǎng)度超過8的時(shí)候,自動(dòng)轉(zhuǎn)換為紅黑樹。
結(jié)論:JDK8開始后,哈希表對(duì)于紅黑樹的引入進(jìn)一步提高了操作數(shù)據(jù)的性能。
HashSet1.8版本原理解析:數(shù)組-鏈表-紅黑樹-(結(jié)合哈希算法)
總結(jié):
Set集合的底層原理是什么樣的?
- JDK8之前,哈希表:底層使用數(shù)組+鏈表組成。
- JDK8開始后,哈希表:底層采用數(shù)組+鏈表+紅黑樹組成。
哈希表的詳細(xì)流程?
-
創(chuàng)建一個(gè)默認(rèn)長(zhǎng)度16,默認(rèn)加載因子0.75的數(shù)組(加載因子 = 存儲(chǔ)數(shù)據(jù)的個(gè)數(shù) / 表的長(zhǎng)度),數(shù)組名為table。
-
根據(jù)元素的哈希值跟數(shù)組的長(zhǎng)度計(jì)算出應(yīng)存入的位置。
-
判斷當(dāng)前位置是否為null,如果是null直接存入,如果位置不為null,表示有元素,則調(diào)用equals方法比較屬性值,如果一樣,則不存,如果不一樣,則存入數(shù)組。
-
當(dāng)數(shù)組存滿到16*0.75=12時(shí),就自動(dòng)擴(kuò)容,每次擴(kuò)容原來的兩倍。
c.HashSet元素去重復(fù)的底層原理
HashSet去重復(fù)原理解析:
結(jié)論:如果希望Set集合認(rèn)為2個(gè)內(nèi)容一樣的對(duì)象是重復(fù)的,必須重寫對(duì)象的hashCode()和equals()方法。
案例:Set集合去重復(fù)
需求:
- 創(chuàng)建一個(gè)存儲(chǔ)學(xué)生對(duì)象的集合,存儲(chǔ)多個(gè)學(xué)生對(duì)象,使用程序?qū)崿F(xiàn)在控制臺(tái)遍歷該集合。
- 要求:學(xué)生對(duì)象的成員變量值相同,我們就認(rèn)為是同一個(gè)對(duì)象。
分析:
- 定義學(xué)生類,創(chuàng)建HashSet集合對(duì)象,創(chuàng)建學(xué)生對(duì)象。
- 把學(xué)生添加到集合。
- 把學(xué)生類中重寫兩個(gè)方法,hashCode()和equals(),自動(dòng)生成即可。
- 遍歷集合(增強(qiáng)for)。
Student.java
import java.util.Objects;public class Student {private String name;private int age;private char sex;public Student() {}public Student(String name, int age, char sex) {this.name = name;this.age = age;this.sex = sex;}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;}public char getSex() {return sex;}public void setSex(char sex) {this.sex = sex;}@Overridepublic String toString() {return "Student{" +"name='" + name + '\'' +", age=" + age +", sex=" + sex +'}';}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (!(o instanceof Student student)) return false;return getAge() == student.getAge() && getSex() == student.getSex() && Objects.equals(getName(), student.getName());}@Overridepublic int hashCode() {return Objects.hash(getName(), getAge(), getSex());} }Test.java
import java.util.HashSet; import java.util.Set;public class Test {public static void main(String[] args) {// 創(chuàng)建學(xué)生對(duì)象哈希集合Set<Student> studentHashSet = new HashSet<>();// 創(chuàng)建學(xué)生對(duì)象Student student1 = new Student("白子畫", 1000, '男');Student student2 = new Student("白子畫", 1000, '男');Student student3 = new Student("花千骨", 16, '女');// 學(xué)生對(duì)象添加到 學(xué)生對(duì)象哈希集合中studentHashSet.add(student1);studentHashSet.add(student2);studentHashSet.add(student3);// 未重寫equals()和hashCode() [Student{name='白子畫', age=1000, sex=男}, Student{name='花千骨', age=16, sex=女}, Student{name='白子畫', age=1000, sex=男}]// 重寫equals()和hashCode() [Student{name='白子畫', age=1000, sex=男}, Student{name='花千骨', age=16, sex=女}]System.out.println(studentHashSet);// 遍歷學(xué)生對(duì)象哈希集合for (Student student : studentHashSet) {System.out.println(student);}} }總結(jié):
- 重寫對(duì)象的hashCode和equals方法。
d.實(shí)現(xiàn)類:LinkedHashSet
LinkedHashSet集合概述和特點(diǎn):
- 有序、不重復(fù)、無索引。
- 這里的有序指的是保證存儲(chǔ)和取出的元素順序一致。
- 原理:底層數(shù)據(jù)結(jié)構(gòu)是哈希表,只是每個(gè)元素又額外多了一個(gè)雙鏈表的機(jī)制記錄存儲(chǔ)的順序。
Test.java
import java.util.LinkedHashSet; import java.util.Set;public class Test {public static void main(String[] args) {// 創(chuàng)建LinkedHashSet對(duì)象// 有序、不重復(fù)、無索引Set<String> linkedHashSet = new LinkedHashSet<>();linkedHashSet.add("MySQL");linkedHashSet.add("MySQL");linkedHashSet.add("Java");linkedHashSet.add("Java");linkedHashSet.add("Python");linkedHashSet.add("Python");// [MySQL, Java, Python]System.out.println(linkedHashSet);} }總結(jié):
- 有序、不重復(fù)、無索引。
- 底層基于哈希表,使用雙鏈表記錄添加順序。
e.實(shí)現(xiàn)類:TreeSet
TreeSet集合概述和特點(diǎn):
- 不重復(fù)、無索引、可排序。
- 可排序:按照元素的大小默認(rèn)升序(由小到大)排序。
- TreeSet集合底層是基于紅黑樹的數(shù)據(jù)結(jié)構(gòu)實(shí)現(xiàn)排序的,增刪改查性能都較好。
- 注意:TreeSet集合是一定要排序的,可以將元素按照指定的規(guī)則進(jìn)行排序。
TreeSet集合默認(rèn)的規(guī)則:
- 對(duì)于數(shù)值類型:Integer、Double,官方按照大小進(jìn)行升序排序。
- 對(duì)于字符串類型:默認(rèn)按照首字符的編號(hào)升序排序。
- 對(duì)于自定義類型如Student對(duì)象,TreeSet無法直接排序。
結(jié)論:想要使用TreeSet存儲(chǔ)自定義類型,需要制定排序規(guī)則。
自定義排序規(guī)則:
- TreeSet集合存儲(chǔ)對(duì)象的時(shí)候有2種方法可以設(shè)計(jì)自定義比較規(guī)則。
- 方式一:讓自定義類(如蘋果類)實(shí)現(xiàn)Comparable接口重寫里面的compareTo()方法來定制比較規(guī)則。
- 方式二:TreeSet集合有參構(gòu)造器,可以設(shè)置Comparable接口對(duì)應(yīng)的比較器對(duì)象,來定制比較規(guī)則。
兩種方式種,關(guān)于返回值的規(guī)則:
- 如果認(rèn)為第一個(gè)元素大于第二個(gè)元素返回正整數(shù)即可。
- 如果認(rèn)為第一個(gè)元素小于第二個(gè)元素返回負(fù)整數(shù)即可。
- 如果認(rèn)為第一個(gè)元素等于第二個(gè)元素返回0即可,此時(shí)TreeSet集合只會(huì)保留一個(gè)元素,認(rèn)為兩者重復(fù)。
注意:如果TreeSet集合存儲(chǔ)的對(duì)象有實(shí)現(xiàn)比較規(guī)則,集合也自帶比較器,默認(rèn)使用集合自帶的比較器排序。
Apple.java
public class Apple implements Comparable<Apple>{private String name;private String color;private double weight;private int id;public Apple() {}public Apple(String name, String color, double weight, int id) {this.name = name;this.color = color;this.weight = weight;this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public double getWeight() {return weight;}public void setWeight(double weight) {this.weight = weight;}public int getId() {return id;}public void setId(int id) {this.id = id;}@Overridepublic String toString() {return "Apple{" +"name='" + name + '\'' +", color='" + color + '\'' +", weight=" + weight +", id=" + id +'}';}/*** 方式一:類自定義比較規(guī)則** @param apple 蘋果類對(duì)象* @return 返回值*/@Overridepublic int compareTo(Apple apple) {// 按照重量進(jìn)行比較 會(huì)去掉重量重復(fù)的元素return Double.compare(this.weight, apple.weight);// 一旦有重量相等情況 認(rèn)為第一個(gè)比第二個(gè)大 此時(shí)不會(huì)去掉重量重復(fù)的元素// return (int) (this.weight - apple.weight) >= 0 ? 1 : -1;} }Test.java
import java.util.Comparator; import java.util.Set; import java.util.TreeSet;public class Test {public static void main(String[] args) {// 不重復(fù)、無索引、可排序// 數(shù)值類型Set<Integer> set = new TreeSet<>();set.add(23);set.add(24);set.add(25);set.add(1);set.add(2);// [1, 2, 23, 24, 25]System.out.println(set);// 字符串類型Set<String> set1 = new TreeSet<>();set1.add("Java");set1.add("Python");set1.add("SQL");set1.add("C++");set1.add("asp");set1.add("易語言");// [C++, Java, Python, SQL, asp, 易語言]System.out.println(set1);// 自定義對(duì)象Set<Apple> appleSet = new TreeSet<>();// 方式二:集合自帶比較器對(duì)象進(jìn)行規(guī)則定制 // Set<Apple> appleSet = new TreeSet<>(new Comparator<Apple>() { // @Override // public int compare(Apple apple, Apple t1) { // return Double.compare(apple.getWeight(), t1.getWeight()); // } // });// Set<Apple> appleSet = new TreeSet<>((apple, t1) -> Double.compare(apple.getWeight(), t1.getWeight()));appleSet.add(new Apple("紅富士", "紅色", 9.9, 1));appleSet.add(new Apple("嘎拉", "紅色", 6.9, 2));appleSet.add(new Apple("澳洲青蘋", "綠色", 5.9, 3));appleSet.add(new Apple("黃元帥", "黃色", 9.9, 4));// [Apple{name='澳洲青蘋', color='綠色', weight=5.9, id=3}, Apple{name='嘎拉', color='紅色', weight=6.9, id=2}, Apple{name='紅富士', color='紅色', weight=9.9, id=1}]System.out.println(appleSet);} }總結(jié):
- 可排序、不重復(fù)、無索引。
- 底層基于紅黑樹實(shí)現(xiàn)排序,增刪改查性能較好。
- 類實(shí)現(xiàn)Comparable接口,重寫比較規(guī)則。
- 集合自定義Comparator比較器對(duì)象,重寫比較規(guī)則。
2.Collection體系特點(diǎn)、使用場(chǎng)景總結(jié)
- 用ArrayList集合,基于數(shù)組。(用的最多)
- 用LinkedList集合,基于鏈表的。
- 用HashSet集合,基于哈希表。
- 用LinkedHashSet集合,基于哈希表和雙鏈表。
- 用TreeSet集合,基于紅黑樹。后續(xù)也可以用List集合實(shí)現(xiàn)排序。
3.補(bǔ)充知識(shí):可變參數(shù)
假如需要定義一個(gè)方法求和,該方法可以靈活的完成如下需求:
- 計(jì)算1個(gè)數(shù)據(jù)的和。
- 計(jì)算2個(gè)數(shù)據(jù)的和。
- 計(jì)算3個(gè)數(shù)據(jù)的和。
- 計(jì)算N個(gè)數(shù)據(jù)的和,甚至可以支持不接受參數(shù)進(jìn)行調(diào)用。
可變參數(shù):
- 可變參數(shù)用在形參種可以接收多個(gè)數(shù)據(jù)。
- 可變參數(shù)的格式:數(shù)據(jù)類型…參數(shù)名稱。
可變參數(shù)的作用:
- 傳輸參數(shù)非常靈活、方便。可以不傳參數(shù),可以傳輸1個(gè)或多個(gè)參數(shù),也可以傳輸一個(gè)數(shù)組。
- 可變參數(shù)再方法內(nèi)部本質(zhì)上就是一個(gè)數(shù)組。
可變參數(shù)的注意事項(xiàng):
- 一個(gè)形參列表中可變參數(shù)只能有一個(gè)。
- 可變參數(shù)必須放在形參列表的最后面。
Test.java
import java.util.Arrays;public class Test {public static void main(String[] args) {sum();sum(1);sum(1, 2);sum(new int[]{10, 20, 30});}public static void sum(int...nums) {// 注意:可變參數(shù)在方法內(nèi)部其實(shí)就是一個(gè)數(shù)組System.out.println("元素個(gè)數(shù):" + nums.length);System.out.println("元素內(nèi)容:" + Arrays.toString(nums));} }4.補(bǔ)充知識(shí):集合工具類Collections
Collections集合工具類:
- java.utils.Collections:是集合工具類。
- 作用:Collections并不屬于集合,是用來操作集合的工具類。
Collections常用的API:
| public static boolean addAll(Collection<? super T> c, T…elements) | 給集合對(duì)象批量添加元素。 |
| public static void shuffle(List<?> list) | 打亂List集合元素的順序。 |
Collection排序相關(guān)API:
- 使用范圍:只能對(duì)于List集合的排序。
| public static void sort(List list) | 將集合中元素按照默認(rèn)規(guī)則排序。 |
注意:本方式不可以直接對(duì)自定義類型的List集合排序,除非自定義類型實(shí)現(xiàn)了比較規(guī)則Comparable接口。
| public static void sort(List list, Comparator<? super T > c) | 將集合中元素按照指定規(guī)則排序。 |
Apple.java
public class Apple implements Comparable<Apple>{private String name;private String color;private double weight;private int id;public Apple() {}public Apple(String name, String color, double weight, int id) {this.name = name;this.color = color;this.weight = weight;this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public double getWeight() {return weight;}public void setWeight(double weight) {this.weight = weight;}public int getId() {return id;}public void setId(int id) {this.id = id;}@Overridepublic String toString() {return "Apple{" +"name='" + name + '\'' +", color='" + color + '\'' +", weight=" + weight +", id=" + id +'}';}/*** 方式一:類自定義比較規(guī)則** @param apple 蘋果類對(duì)象* @return 返回值*/@Overridepublic int compareTo(Apple apple) {// 按照重量進(jìn)行比較 會(huì)去掉重量重復(fù)的元素return Double.compare(this.weight, apple.getWeight());// 一旦有重量相等情況 認(rèn)為第一個(gè)比第二個(gè)大 此時(shí)不會(huì)去掉重量重復(fù)的元素// return (int) (this.weight - apple.weight) >= 0 ? 1 : -1;} }Test.java
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List;public class Test {public static void main(String[] args) {/* String 類型 */// 創(chuàng)建集合對(duì)象List<String> nameList = new ArrayList<>();// nameList.add("白子畫"); // nameList.add("花千骨"); // nameList.add("殺阡陌"); // nameList.add("輕水"); // nameList.add("霓漫天");// 集合批量添加數(shù)據(jù)Collections.addAll(nameList, "白子畫", "花千骨", "殺阡陌", "輕水", "霓漫天");// [白子畫, 花千骨, 殺阡陌, 輕水, 霓漫天]System.out.println(nameList);// 打亂List集合順序Collections.shuffle(nameList);// [殺阡陌, 霓漫天, 白子畫, 輕水, 花千骨]System.out.println(nameList);/* Integer 類型 */List<Integer> list = new ArrayList<>();// 集合批量添加數(shù)據(jù)Collections.addAll(list, 7, 5, 10, 6);// [7, 5, 10, 6]System.out.println(list);// List集合排序Collections.sort(list);// [5, 6, 7, 10]System.out.println(list);/* 自定義類型 */List<Apple> appleList = new ArrayList<>();appleList.add(new Apple("紅富士", "紅色", 9.9, 1));appleList.add(new Apple("嘎拉", "紅色", 6.9, 2));appleList.add(new Apple("澳洲青蘋", "綠色", 5.9, 3));appleList.add(new Apple("黃元帥", "黃色", 9.9, 4));// 方式一:Apple類已經(jīng)重寫了比較規(guī)則 可以進(jìn)行排序Collections.sort(appleList);// [Apple{name='澳洲青蘋', color='綠色', weight=5.9, id=3}, Apple{name='嘎拉', color='紅色', weight=6.9, id=2}, Apple{name='紅富士', color='紅色', weight=9.9, id=1}, Apple{name='黃元帥', color='黃色', weight=9.9, id=4}]System.out.println(appleList);// 方式二Collections.sort(appleList, new Comparator<Apple>() {@Overridepublic int compare(Apple apple, Apple t1) {return Double.compare(apple.getWeight(), t1.getWeight());}});// [Apple{name='澳洲青蘋', color='綠色', weight=5.9, id=3}, Apple{name='嘎拉', color='紅色', weight=6.9, id=2}, Apple{name='紅富士', color='紅色', weight=9.9, id=1}, Apple{name='黃元帥', color='黃色', weight=9.9, id=4}]System.out.println(appleList);// 使用lambda簡(jiǎn)化寫法Collections.sort(appleList, (apple, t1) -> Double.compare(apple.getWeight(), t1.getWeight()));System.out.println(appleList);} }5.Collection體系的綜合案例
Ⅰ.案例:斗地主游戲
需求:
- 在啟動(dòng)游戲房間的時(shí)候,應(yīng)該提前準(zhǔn)備好54張牌,完成洗牌、發(fā)牌、牌排序邏輯。
分析:
- 當(dāng)系統(tǒng)啟動(dòng)的同時(shí)需要準(zhǔn)備好數(shù)據(jù)的時(shí)候,就可用用靜態(tài)代碼塊。
- 洗牌就是打亂牌的順序。
- 定義三個(gè)玩家,依次發(fā)出51張牌。
- 給玩家的牌進(jìn)行排序(拓展)。
- 輸出每個(gè)玩家的牌數(shù)據(jù)。
Card.java
public class Card {// 牌的花色private String color;// 牌的點(diǎn)數(shù)private String size;// 牌的真實(shí)大小private int index;public Card() {}public Card(String color, String size, int index) {this.color = color;this.size = size;this.index = index;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public String getSize() {return size;}public void setSize(String size) {this.size = size;}public int getIndex() {return index;}public void setIndex(int index) {this.index = index;}@Overridepublic String toString() {return color + size;} }Landlords.java
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List;public class Landlords {/*** 1.創(chuàng)建集合存儲(chǔ)54張牌對(duì)象*/public static List<Card> cardList = new ArrayList<>();/*** 2.定義靜態(tài)代碼塊初始化牌數(shù)據(jù)*/static {// 定義花色String[] colors = {"黑桃", "紅桃", "梅花", "方塊"};// 定義點(diǎn)數(shù)String[] sizes = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};// 組合點(diǎn)數(shù)和花色int index = 0;for (String size : sizes) {// 相同點(diǎn)數(shù) 大小值一樣index++;for (String color : colors) {// 創(chuàng)建牌Card card = new Card(color, size, index);// 將牌添加到牌集合對(duì)象中cardList.add(card);}}// 大小王存入到牌集合對(duì)象中Card jokerGrey = new Card("灰", "Joker", ++index);Card jokerRed = new Card("紅", "Joker", ++index);Collections.addAll(cardList, jokerGrey, jokerRed);System.out.println("新牌" + cardList);}public static void main(String[] args) {// 洗牌Collections.shuffle(cardList);System.out.println("洗牌后" + cardList);// 定義三個(gè)玩家 每個(gè)玩家的牌也是一個(gè)集合容器List<Card> ZhangSan = new ArrayList<>();List<Card> Lisi = new ArrayList<>();List<Card> WangWu = new ArrayList<>();// 發(fā)牌 從牌集合中發(fā)出51張牌給三個(gè)玩家 剩余三張作為底牌for (int i = 0; i < cardList.size() - 3; i++) {// 當(dāng)前牌對(duì)象Card card = cardList.get(i);if (i % 3 == 0) {ZhangSan.add(card);} else if (i % 3 == 1) {Lisi.add(card);} else {WangWu.add(card);}}// 底牌List<Card> holeCard = cardList.subList(cardList.size() - 3, cardList.size());// 玩家牌進(jìn)行排序sortCard(ZhangSan);sortCard(Lisi);sortCard(WangWu);sortCard(holeCard);// 查看發(fā)牌結(jié)果System.out.println("張三" + ZhangSan);System.out.println("李四" + Lisi);System.out.println("王五" + WangWu);System.out.println("三張底牌" + holeCard);}/*** 對(duì)牌集合進(jìn)行排序** @param cardList: 牌集合*/private static void sortCard(List<Card> cardList) {cardList.sort(new Comparator<Card>() {@Overridepublic int compare(Card card1, Card card2) {return card2.getIndex() - card1.getIndex();}});} }6.Map集合體系
a.Map集合的概述
Map集合概述和使用:
- Map集合是一種雙列集合,每個(gè)元素包含兩個(gè)數(shù)據(jù)。
- Map集合的每個(gè)元素的格式:key=value(鍵值對(duì)元素)。
- Map集合也被稱為“鍵值對(duì)集合”。
Map集合整體格式:
- Collection集合的格式:[元素1, 元素2, 元素3]。
- Map集合的完整格式:{key1=value1, key2=value2, key3=value3, …}。
Map集合的使用場(chǎng)景之一:購(gòu)物車系統(tǒng):
分析:
- 購(gòu)物車提供的四個(gè)商品和購(gòu)買的數(shù)量在后臺(tái)需要容器存儲(chǔ)。
- 每個(gè)商品對(duì)象都一一對(duì)應(yīng)一個(gè)購(gòu)買數(shù)量。
- 把商品對(duì)象看成是Map集合的鍵,購(gòu)買數(shù)量看成Map集合的值。
總結(jié):
- Map集合是鍵值對(duì)集合。
- Map集合非常適合做類似購(gòu)物車這樣的業(yè)務(wù)場(chǎng)景。
b.Map集合體系特點(diǎn)
#mermaid-svg-x7vP9MAWeu4s62l0 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-x7vP9MAWeu4s62l0 .error-icon{fill:#552222;}#mermaid-svg-x7vP9MAWeu4s62l0 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-x7vP9MAWeu4s62l0 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-x7vP9MAWeu4s62l0 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-x7vP9MAWeu4s62l0 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-x7vP9MAWeu4s62l0 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-x7vP9MAWeu4s62l0 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-x7vP9MAWeu4s62l0 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-x7vP9MAWeu4s62l0 .marker.cross{stroke:#333333;}#mermaid-svg-x7vP9MAWeu4s62l0 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-x7vP9MAWeu4s62l0 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-x7vP9MAWeu4s62l0 .cluster-label text{fill:#333;}#mermaid-svg-x7vP9MAWeu4s62l0 .cluster-label span{color:#333;}#mermaid-svg-x7vP9MAWeu4s62l0 .label text,#mermaid-svg-x7vP9MAWeu4s62l0 span{fill:#333;color:#333;}#mermaid-svg-x7vP9MAWeu4s62l0 .node rect,#mermaid-svg-x7vP9MAWeu4s62l0 .node circle,#mermaid-svg-x7vP9MAWeu4s62l0 .node ellipse,#mermaid-svg-x7vP9MAWeu4s62l0 .node polygon,#mermaid-svg-x7vP9MAWeu4s62l0 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-x7vP9MAWeu4s62l0 .node .label{text-align:center;}#mermaid-svg-x7vP9MAWeu4s62l0 .node.clickable{cursor:pointer;}#mermaid-svg-x7vP9MAWeu4s62l0 .arrowheadPath{fill:#333333;}#mermaid-svg-x7vP9MAWeu4s62l0 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-x7vP9MAWeu4s62l0 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-x7vP9MAWeu4s62l0 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-x7vP9MAWeu4s62l0 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-x7vP9MAWeu4s62l0 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-x7vP9MAWeu4s62l0 .cluster text{fill:#333;}#mermaid-svg-x7vP9MAWeu4s62l0 .cluster span{color:#333;}#mermaid-svg-x7vP9MAWeu4s62l0 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-x7vP9MAWeu4s62l0 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} Map 接口 HashMap 實(shí)現(xiàn)類 HashTable 實(shí)現(xiàn)類 ... 接口 LinkedHashMap 實(shí)現(xiàn)類 Properties 實(shí)現(xiàn)類 TreeMap 實(shí)現(xiàn)類說明:
- 使用最多的Map集合是HashMap。
- 重點(diǎn)掌握HashMap,LinkedHashMap,TreeMap。其他的后續(xù)理解。
Map集合體系特點(diǎn):
-
Map集合的特點(diǎn)都是由鍵決定的。
-
Map集合的鍵是無序、不重復(fù)的,Map集合后面重復(fù)的鍵對(duì)應(yīng)的值會(huì)覆蓋前面重復(fù)鍵的值。
-
Map集合的值不做要求、可以重復(fù)。
-
Map集合的鍵值對(duì)都可以為null。
Map集合實(shí)現(xiàn)類特點(diǎn):
-
HashMap:元素按照鍵是無序、不重復(fù)、無索引,值不做要求。(與Map體系一致)
import java.util.HashMap; import java.util.Map;/*** 目標(biāo):認(rèn)識(shí)Map體系的特點(diǎn):按照無序、不重復(fù)、無索引。*/ public class Test {public static void main(String[] args) {// 創(chuàng)建一個(gè)Map集合對(duì)象Map<String, Integer> stringIntegerMap = new HashMap<>();stringIntegerMap.put("固態(tài)硬盤", 1);stringIntegerMap.put("HDMI線", 2);stringIntegerMap.put("顯示屏", 1);stringIntegerMap.put("顯示屏", 2);stringIntegerMap.put("鍵盤", 1);stringIntegerMap.put(null, null);// {HDMI線=2, null=null, 固態(tài)硬盤=1, 鍵盤=1, 顯示屏=2}System.out.println(stringIntegerMap);} } -
LinkedHashMap:元素按照鍵是有序、不重復(fù)、無索引、值不做要求。
import java.util.LinkedHashMap; import java.util.Map;public class Test {public static void main(String[] args) {// 創(chuàng)建一個(gè)Map集合對(duì)象Map<String, Integer> stringIntegerMap = new LinkedHashMap<>();stringIntegerMap.put("HDMI線", 2);stringIntegerMap.put("顯示屏", 1);stringIntegerMap.put("顯示屏", 2);stringIntegerMap.put("鍵盤", 1);stringIntegerMap.put("固態(tài)硬盤", 1);stringIntegerMap.put(null, null);// {HDMI線=2, 顯示屏=2, 鍵盤=1, 固態(tài)硬盤=1, null=null}System.out.println(stringIntegerMap);} } -
TreeMap:元素按照鍵排序,不重復(fù)、無索引、值不做要求。
c.Map集合常用API
Map集合:
- Map是雙列集合的祖宗接口,它的功能是全部雙列集合都可以繼承使用的。
Map API如下:
| V put(K key, V value) | 添加元素。 |
| V remove(Object key) | 根據(jù)鍵刪除鍵值對(duì)元素。 |
| void clear() | 移除所有的鍵值對(duì)元素。 |
| boolean containsKey(Object key) | 判斷集合是否包括指定的鍵。 |
| boolean containValue(Object value) | 判斷集合是否包含指定的值。 |
| boolean isEmpty() | 判斷集合是否為空。 |
| int size() | 集合的長(zhǎng)度,也就是集合中鍵值對(duì)的個(gè)數(shù)。 |
Test.java
import java.util.HashMap; import java.util.Map;public class Test {public static void main(String[] args) {// 創(chuàng)建一個(gè)Map集合對(duì)象Map<String, Integer> stringIntegerMap = new HashMap<>();stringIntegerMap.put("固態(tài)硬盤", 1);stringIntegerMap.put("HDMI線", 2);stringIntegerMap.put("顯示屏", 1);stringIntegerMap.put("顯示屏", 2);stringIntegerMap.put("鍵盤", 1);stringIntegerMap.put(null, null);// {HDMI線=2, null=null, 固態(tài)硬盤=1, 鍵盤=1, 顯示屏=2}System.out.println(stringIntegerMap);// 判斷集合是否為空 為空返回true 反之返回falseSystem.out.println(stringIntegerMap.isEmpty());// 根據(jù)鍵獲取對(duì)應(yīng)值 沒有該鍵返回nullSystem.out.println(stringIntegerMap.get("顯示屏"));// 根據(jù)鍵刪除整個(gè)元素 刪除鍵會(huì)返回鍵的值System.out.println(stringIntegerMap.remove("顯示屏"));// 判斷是否包含某個(gè)鍵 包含返回true 反之返回falseSystem.out.println(stringIntegerMap.containsKey("鍵盤"));// 判斷是否包含某個(gè)值System.out.println(stringIntegerMap.containsValue(1));// 獲取全部鍵的集合System.out.println(stringIntegerMap.keySet());// 獲取全部值得集合System.out.println(stringIntegerMap.values());// 集合的大小System.out.println(stringIntegerMap.size());// 合并其他Map集合Map<String, Integer> map = new HashMap<>();map.put("短袖", 1);map.put("短褲", 1);map.put("襪子", 3);map.put("運(yùn)動(dòng)鞋", 1);// 集合map的元素拷貝一份到stringIntegerMap中stringIntegerMap.putAll(map);System.out.println(stringIntegerMap);// 清空集合stringIntegerMap.clear();System.out.println(stringIntegerMap);} }d.Map集合的遍歷方式一:鍵找值
遍歷Map集合方式一:鍵找值
- 先獲取Map集合的全部鍵的Set集合。
- 遍歷鍵的Set集合,然后通過鍵提取對(duì)應(yīng)值。
鍵找到值涉及到的API:
| Set keySet() | 獲取所有鍵的集合。 |
| V get(Object key) | 根據(jù)鍵獲取值。 |
Test.java
import java.util.HashMap; import java.util.Map; import java.util.Set;public class Test {public static void main(String[] args) {// 創(chuàng)建一個(gè)Map集合對(duì)象Map<String, Integer> stringIntegerMap = new HashMap<>();stringIntegerMap.put("固態(tài)硬盤", 1);stringIntegerMap.put("HDMI線", 2);stringIntegerMap.put("顯示屏", 1);stringIntegerMap.put("顯示屏", 2);stringIntegerMap.put("鍵盤", 1);// 獲取集合所有鍵Set<String> keySet = stringIntegerMap.keySet();for (String key : keySet) {int value = stringIntegerMap.get(key);System.out.println(key + ":" + value);}} }e.Map集合的遍歷方式二:鍵值對(duì)
遍歷Map集合方式二:鍵值對(duì)。
- 先把Map集合轉(zhuǎn)換成Set集合,Set集合中每個(gè)元素都是鍵值對(duì)實(shí)體類型。
- 遍歷Set集合,然后提取鍵以及提取值。
鍵值對(duì)涉及到的API:
| Set<Map.Entry<K, V>> entrySet() | 獲取所有鍵值對(duì)對(duì)象的集合。 |
| K getKey() | 獲得鍵。 |
| V getValue() | 獲取值。 |
Test.java
import java.util.HashMap; import java.util.Map; import java.util.Set;public class Test {public static void main(String[] args) {// 創(chuàng)建一個(gè)Map集合對(duì)象Map<String, Integer> stringIntegerMap = new HashMap<>();stringIntegerMap.put("固態(tài)硬盤", 1);stringIntegerMap.put("HDMI線", 2);stringIntegerMap.put("顯示屏", 1);stringIntegerMap.put("顯示屏", 2);stringIntegerMap.put("鍵盤", 1);// {HDMI線=2, 固態(tài)硬盤=1, 鍵盤=1, 顯示屏=2}System.out.println(stringIntegerMap);/* 使用foreach遍歷map集合,發(fā)現(xiàn)Map集合的鍵值對(duì)元素直接是沒有類型的 所以不可以直接foreach遍歷集合* 可以通過調(diào)用Map的方法 entrySet把Map集合轉(zhuǎn)換成Set集合形式——Set集合中是Map實(shí)體類型-鍵值對(duì)類型* Set<Map.Entry<String, Integer>> entries = [(HDMI線=2), (固態(tài)硬盤=1), (鍵盤=1), (顯示屏=2)]* */// 把Map集合轉(zhuǎn)換成Set集合Set<Map.Entry<String, Integer>> entries = stringIntegerMap.entrySet();// 遍歷for (Map.Entry<String, Integer> entry : entries) {System.out.println(entry);System.out.println(entry.getKey() + ":" + entry.getValue());}} }f.Map集合的遍歷方式三:lambda表達(dá)式
Map集合的遍歷方式三:Lambda
- 得益于JDK 8開始的新技術(shù)Lambda表達(dá)式,提供了一種更簡(jiǎn)單、更直接的遍歷集合的方式。
Map結(jié)合Lambda遍歷的API
| default void forEach(BiConsumer<? super k, ? super V> action) | 結(jié)合lambda遍歷Map集合。 |
Test.java
import java.util.HashMap; import java.util.Map; import java.util.function.BiConsumer;public class Test {public static void main(String[] args) {// 創(chuàng)建一個(gè)Map集合對(duì)象Map<String, Integer> stringIntegerMap = new HashMap<>();stringIntegerMap.put("固態(tài)硬盤", 1);stringIntegerMap.put("HDMI線", 2);stringIntegerMap.put("顯示屏", 1);stringIntegerMap.put("顯示屏", 2);stringIntegerMap.put("鍵盤", 1);// {HDMI線=2, 固態(tài)硬盤=1, 鍵盤=1, 顯示屏=2}System.out.println(stringIntegerMap);stringIntegerMap.forEach(new BiConsumer<String, Integer>() {@Overridepublic void accept(String key, Integer value) {System.out.println(key + ":" + value);}});stringIntegerMap.forEach((key, value) -> System.out.println(key + ":" + value));} }g.Map集合案例
Map集合案例-統(tǒng)計(jì)投票人數(shù)
需求:
- 某個(gè)班級(jí)80名學(xué)生,現(xiàn)在需要組成秋游活動(dòng),班長(zhǎng)提供了四個(gè)景點(diǎn)依次是(A、B、C、D),每個(gè)學(xué)生只能選擇一個(gè)景點(diǎn),請(qǐng)統(tǒng)計(jì)出最終哪個(gè)景點(diǎn)想去的人數(shù)最多。
分析:
- 將80個(gè)學(xué)生選擇的數(shù)據(jù)拿到程序中去。
- 定義Map集合用于存儲(chǔ)最終統(tǒng)計(jì)的結(jié)果。
- 遍歷80個(gè)學(xué)生選擇的數(shù)據(jù),看Map集合中是否存在,不存在存入“數(shù)據(jù)=1”,存在則其對(duì)應(yīng)值+1。
Test.java
import java.util.HashMap; import java.util.Map; import java.util.Random;public class Test {public static void main(String[] args) {// 把80個(gè)學(xué)生選擇的數(shù)據(jù)拿進(jìn)來String[] selects = {"A", "B", "C", "D"};StringBuilder stringBuilder = new StringBuilder();Random random = new Random();// 生成數(shù)據(jù) 循環(huán)80次for (int i = 0; i < 80; i++) {// 從A B C D中選擇其一stringBuilder.append(selects[random.nextInt(selects.length)]);}// 定義一個(gè)Map集合記錄最終統(tǒng)計(jì)的結(jié)果: A=30 B=20 C=20 D=10 景點(diǎn)是鍵 出現(xiàn)次數(shù)是值Map<Character, Integer> stringIntegerMap = new HashMap<>();for (int i = 0; i < stringBuilder.length(); i++) {// 提取當(dāng)前景點(diǎn)字符char ch = stringBuilder.charAt(i);// 判斷鍵是否存在于Map集合中if (stringIntegerMap.containsKey(ch)) {// 如果景點(diǎn)存在 出現(xiàn)次數(shù)+1stringIntegerMap.put(ch, stringIntegerMap.get(ch) + 1);} else {// 如果景點(diǎn)初次被選 出現(xiàn)次數(shù)初始化為1stringIntegerMap.put(ch, 1);}}// {A=22, B=18, C=26, D=14}System.out.println(stringIntegerMap);} }h.Map集合的實(shí)現(xiàn)類HashMap
HashMap的特點(diǎn):
- HashMap是Map里面的一個(gè)實(shí)現(xiàn)類。特點(diǎn)都是由鍵決定的:無序、不重復(fù)、無索引。
- 沒有額外需要學(xué)習(xí)的特有方法,直接使用Map里面的方法就可以了。
- HashMap跟HashSet底層原理是一摸一樣的,都是哈希表結(jié)構(gòu),只是HashMap的每個(gè)元素包含兩個(gè)值而已。
實(shí)際上:Set系列集合的底層就是Map實(shí)現(xiàn)的,只是Set集合中的元素只要鍵數(shù)據(jù),不要值數(shù)據(jù)而已。
總結(jié):
- 由鍵決定:無序、不重復(fù)、無索引。HashMap底層都是哈希表結(jié)構(gòu)。
- 依賴hashCode()和equals()保證鍵的唯一。
- 如果鍵要存儲(chǔ)的是自定義對(duì)象,需要重寫hashCode和equals方法。
- 基于哈希表,增刪改查的性能都較好。
i.Map集合的實(shí)現(xiàn)類LinkedHashMap
LinkedHashMap集合概述和特點(diǎn):
- 由鍵決定:有序、不重復(fù)、無索引。
- 這里的有序指的是保證存儲(chǔ)和取出的元素順序一致。
- 原理:底層數(shù)據(jù)結(jié)構(gòu)依然是哈希表,只是每個(gè)鍵值對(duì)元素又額外的多了一個(gè)雙鏈表的機(jī)制,記錄存儲(chǔ)的順序。
j.Map集合的實(shí)現(xiàn)類TreeMap
TreeMap集合概述和特點(diǎn):
- 由鍵決定特性:不重復(fù)、無索引、可排序。
- 可排序:按照鍵數(shù)據(jù)的大小默認(rèn)升序(由小到大)排序。只能對(duì)鍵排序。
- 注意:TreeMap集合是一定要排序的,可以默認(rèn)排序,也可以將鍵按照指定的規(guī)則進(jìn)行排序。
- TreeMap跟TreeSet底層原理是一樣的。
TreeMap集合自定義排序規(guī)則有2種:
- 類實(shí)現(xiàn)Comparable接口,重寫比較規(guī)則。
- 集合自定義Comparator比較器對(duì)象,重寫比較規(guī)則。
Apple.java
public class Apple implements Comparable<Apple>{private String name;private String color;private double weight;private int id;public Apple() {}public Apple(String name, String color, double weight, int id) {this.name = name;this.color = color;this.weight = weight;this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getColor() {return color;}public void setColor(String color) {this.color = color;}public double getWeight() {return weight;}public void setWeight(double weight) {this.weight = weight;}public int getId() {return id;}public void setId(int id) {this.id = id;}@Overridepublic String toString() {return "Apple{" +"name='" + name + '\'' +", color='" + color + '\'' +", weight=" + weight +", id=" + id +'}';}/*** 方式一:類自定義比較規(guī)則** @param apple 蘋果類對(duì)象* @return 返回值*/@Overridepublic int compareTo(Apple apple) {// 按照重量進(jìn)行比較 會(huì)去掉重量重復(fù)的元素return Double.compare(this.weight, apple.getWeight());// 一旦有重量相等情況 認(rèn)為第一個(gè)比第二個(gè)大 此時(shí)不會(huì)去掉重量重復(fù)的元素// return (int) (this.weight - apple.weight) >= 0 ? 1 : -1;} }Test.java
import java.util.Comparator; import java.util.Map; import java.util.TreeMap;public class Test {public static void main(String[] args) {/* TreeMap集合自帶排序 可排序 不重復(fù)(只要大小規(guī)則一樣就認(rèn)為重復(fù)) 無索引*/Map<Integer, String> map = new TreeMap<>();map.put(12, "張三");map.put(2, "李四");map.put(3, "王五");// {2=李四, 3=王五, 12=張三}System.out.println(map);// 蘋果按照重量排序Map<Apple, String> appleStringMap = new TreeMap<>(new Comparator<Apple>() {@Overridepublic int compare(Apple apple1, Apple apple2) {return Double.compare(apple1.getWeight(), apple2.getWeight());}});appleStringMap.put(new Apple("紅富士", "紅色", 9.9, 1), "河南");appleStringMap.put(new Apple("嘎拉", "紅色", 6.9, 2), "甘肅");appleStringMap.put(new Apple("澳洲青蘋", "綠色", 5.9, 3), "新疆");appleStringMap.put(new Apple("黃元帥", "黃色", 9.9, 4), "陜西");// {Apple{name='澳洲青蘋', color='綠色', weight=5.9, id=3}=新疆, Apple{name='嘎拉', color='紅色', weight=6.9, id=2}=甘肅, Apple{name='紅富士', color='紅色', weight=9.9, id=1}=陜西}System.out.println(appleStringMap);} }k.Map集合總結(jié)
Map集合實(shí)現(xiàn)類特點(diǎn):
- HashMap:元素按照鍵是無序、不重復(fù)、無索引,值不做要求,基于哈希表(與Map體系一致)。
- LinkedHashMap:元素按照鍵是有序、不重復(fù)、無索引、值不做要求,基于哈希表。
- TreeMap:元素只能按照鍵排序、不重復(fù)、無索引、值不做要求,可以做排序。
7.補(bǔ)充知識(shí):集合的嵌套
a.案例
Map集合案例-統(tǒng)計(jì)投票人數(shù)
需求:
- 某個(gè)班級(jí)多名學(xué)生,現(xiàn)在需要組成秋游活動(dòng),班長(zhǎng)提供了四個(gè)景點(diǎn)依次是A、B、C、D,每個(gè)學(xué)生可以選擇多個(gè)景點(diǎn),請(qǐng)統(tǒng)計(jì)出最終哪個(gè)景點(diǎn)想去的人數(shù)最多。
分析:
- 將80個(gè)學(xué)生選擇的數(shù)據(jù)拿到程序中去,需要記住每個(gè)學(xué)生選擇的情況。
- 定義Map集合用于存儲(chǔ)最終統(tǒng)計(jì)的結(jié)果。
Test.java
import java.util.*;public class Test {public static void main(String[] args) {// 使用Map集合存儲(chǔ)記錄每個(gè)學(xué)生選擇的情況Map<String, List<String>> data = new HashMap<>();// 學(xué)生選擇的數(shù)據(jù)存入List<String> select1 = new ArrayList<>();Collections.addAll(select1, "A", "B", "C");data.put("趙大", select1);List<String> select2 = new ArrayList<>();Collections.addAll(select2, "B", "C");data.put("錢二", select2);List<String> select3 = new ArrayList<>();Collections.addAll(select3, "A", "C");data.put("孫三", select3);// {趙大=[A, B, C], 錢二=[B, C], 孫三=[B, C]}System.out.println(data);// 統(tǒng)計(jì)每個(gè)景點(diǎn)選擇的人數(shù)Map<String, Integer> map = new HashMap<>();// 提取所有人選擇的景點(diǎn)信息// [[A, B, C], [B, C], [A, C]]Collection<List<String>> valuesList = data.values();for (List<String> values : valuesList) {for (String value : values) {if (map.containsKey(value)) {map.put(value, map.get(value) + 1);} else {map.put(value, 1);}}}// {A=2, B=2, C=3}System.out.println(map);} }總結(jié)
以上是生活随笔為你收集整理的Java进阶(七)Set系列集合、Map集合体系的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国产数据库普及风暴有奖征文获奖名单揭晓
- 下一篇: java美元兑换,(Java实现) 美元