日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > java >内容正文

java

Java进阶(七)Set系列集合、Map集合体系

發(fā)布時(shí)間:2024/3/13 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java进阶(七)Set系列集合、Map集合体系 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

七.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é):

  • Set系列集合的特點(diǎn)?
    • 無序、不沖股份、無索引。
  • Set集合的實(shí)現(xiàn)類特點(diǎn)?
    • 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é)合哈希算法)

  • 創(chuàng)建一個(gè)默認(rèn)長(zhǎng)度16的數(shù)組,數(shù)組名table。
  • 根據(jù)元素的哈希值跟數(shù)組的長(zhǎng)度求余計(jì)算處應(yīng)存入的位置(哈希算法)。
  • 判斷當(dāng)前位置是否為null,如果是null直接存入。
  • 如果位置不為null,表示有元素,則調(diào)用equals方法比較。
  • 如果一樣,則不存,如果不一樣,則存入數(shù)組。
    • 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ù)原理解析:

  • 創(chuàng)建一個(gè)默認(rèn)長(zhǎng)度16的數(shù)組,數(shù)組名table。
  • 根據(jù)元素的哈希值跟數(shù)組的長(zhǎng)度求余計(jì)算處應(yīng)存入的位置(哈希算法)。
  • 判斷當(dāng)前位置是否為null,如果是null直接存入。
  • 如果位置不為null,表示有元素,則調(diào)用equals方法比較。
  • 如果一樣,則不存,如果不一樣,則存入數(shù)組。
  • 結(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é):

  • 如果希望Set集合認(rèn)為2個(gè)內(nèi)容相同的對(duì)象是重復(fù)的應(yīng)該怎么辦?
    • 重寫對(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é):

  • LinkedHashSet集合的特點(diǎn)和原理是怎么樣的?
    • 有序、不重復(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é):

  • TreeSet集合的特點(diǎn)是怎么樣的?
    • 可排序、不重復(fù)、無索引。
    • 底層基于紅黑樹實(shí)現(xiàn)排序,增刪改查性能較好。
  • TreeSet集合自定義排序規(guī)則有幾種方式?
    • 類實(shí)現(xiàn)Comparable接口,重寫比較規(guī)則。
    • 集合自定義Comparator比較器對(duì)象,重寫比較規(guī)則。
  • 2.Collection體系特點(diǎn)、使用場(chǎng)景總結(jié)

  • 如果希望元素可以重復(fù)、又有索引,索引查詢要快?
    • 用ArrayList集合,基于數(shù)組。(用的最多)
  • 如果希望元素可以重復(fù),又有索引,增刪首尾操作快?
    • 用LinkedList集合,基于鏈表的。
  • 如果希望增刪改查都快,但是元素不重復(fù)、無序、無索引。
    • 用HashSet集合,基于哈希表。
  • 如果希望增刪改查都快,但是元素不重復(fù)、有序、無索引。
    • 用LinkedHashSet集合,基于哈希表和雙鏈表。
  • 如果要對(duì)對(duì)象進(jìn)行排序。
    • 用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集合的值。
    {商品1=2, 商品2=3, 商品3=2, 商品4=1}

    總結(jié):

  • Map集合是什么?使用場(chǎng)景是什么樣的?
    • 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é):

  • HashMap的特點(diǎn)和底層原理?
    • 由鍵決定:無序、不重復(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)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。