Java之Collections、Set、Map
第一章 Collections類
知識點-- Collections常用功能
目標
- 能夠使用集合工具類Collections
路徑
- 程式碼演示
講解
-
java.utils.Collections
是集合工具類,用來對集合進行操作。常用方法如下:
-
public static void shuffle(List<?> list)
:打亂集合順序。 -
public static <T> void sort(List<T> list)
:將集合中元素按照預設規則排序。 -
public static <T> void sort(List<T> list,Comparator<? super T> com )
程式碼演示:
/** * public static void shuffle(List<?> list):打亂集合中元素的順序。 */ private static void method01() { // 建立一個List集合物件,限制集合中元素型別為Integer List<Integer> list = new ArrayList<>(); // 往集合中新增一些元素 list.add(300); list.add(100); list.add(200); list.add(500); list.add(400); System.out.println("打亂順序之前:"+list);// 打亂順序之前:[300, 100, 200, 500, 400] // 隨機打亂集合中元素的順序:public static void shuffle(List<?> list) Collections.shuffle(list); System.out.println("打亂順序之後:"+list); } /** * public static <T> void sort(List<T> list):將集合中元素按照預設規則排序。 * 集合中的元素為系統類的物件 */ private static void method02() { // 建立一個List集合物件,限制集合中元素型別為Integer List<Integer> list = new ArrayList<>(); // 往集合中新增一些元素 list.add(300); list.add(100); list.add(200); list.add(500); list.add(400); System.out.println("排序之前的集合:"+list);// 打亂順序之前:[300, 100, 200, 500, 400] // 將集合中元素按照預設規則排序: public static <T> void sort(List<T> list) Collections.sort(list); System.out.println("排序之後的集合:"+list);// 排序之後的集合:[100, 200, 300, 400, 500] }
我們的集合按照預設的自然順序進行了排列,如果想要指定順序那該怎麼辦呢?
知識點-- Comparator比較器
目標
- 能夠使用Comparator比較器進行排序
路徑
- 程式碼演示
講解
public static void main(String[] args) { /* Collections常用功能: - public static void shuffle(List<?> list):打亂集合中元素的順序。 - public static <T> void sort(List<T> list):將集合中元素按照預設規則排序。 預設規則: 事先寫好的規則 對集合中的元素按照預設規則排序,要求該集合元素所屬的類實現Comparable介面,重寫compareTo()方法 然後在compareTo()方法中指定排序的預設規則 - public static <T> void sort(List<T> list,Comparator<? super T> ):將集合中元素按照指定規則排序。 指定規則: 自己定義的規則 引數Comparator<T>介面:也稱比較器介面,用來指定排序的規則 */ // 建立一個List集合物件,限制集合中元素型別為Integer List<Integer> list = new ArrayList<>(); // 往集合中新增一些元素 list.add(300); list.add(100); list.add(200); list.add(500); list.add(400); System.out.println("排序之前的集合:"+list);// 打亂順序之前:[300, 100, 200, 500, 400] // 300 100 200 500 400 // 300 // 對list集合指定規則排序: 降序 Collections.sort(list, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // 指定排序規則 // 前減後:升序 // 後減前:降序 // 前:第一個引數 o1 // 後:第二個引數 o2 return o2 - o1; } }); System.out.println("排序之後的集合:"+list);// 排序之後的集合:[500, 400, 300, 200, 100] // 對list集合指定規則排序: 升序 Collections.sort(list, new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { // 指定排序規則 // 前減後:升序 // 後減前:降序 // 前:第一個引數 o1 // 後:第二個引數 o2 return o1 - o2; } }); System.out.println("排序之後的集合:"+list);// 排序之後的集合:[100, 200, 300, 400, 500] }
知識點-- 可變引數
目標
- 能夠使用可變引數
路徑
- 可變引數的使用
- 注意事項
- 應用場景: Collections
講解
可變引數的使用
在JDK1.5之後,如果我們定義一個方法需要接受多個引數,並且多個引數型別一致,我們可以對其簡化.
格式:
修飾符 返回值型別 方法名(引數型別... 形參名){ }
程式碼演示:
public class Demo {
public static void main(String[] args) {
// 可變引數的語法
/*int[] arr = {10, 20, 30, 40, 50, 60};
// 呼叫method1方法
method1(10, 20, 30, 40, 50);
// 呼叫method2方法
method2(arr);
method2(10, 20, 30, 40, 50, 60);
//
method3(arr);
method3(10, 20, 30, 40, 50, 60);
method4(10,"jack","rose");*/
}
public static void method4(int num,String... str){
}
// 定義一個方法,可以接收5個int型別的引數
public static void method3(int[] arr) {
for (int i : arr) {
System.out.println(i);
}
System.out.println(arr[0]);
}
// 定義一個方法,可以接收5個int型別的引數
public static void method2(int... num) {
for (int i : num) {
System.out.println(i);
}
System.out.println(num[0]);
}
// 定義一個方法,可以接收5個int型別的引數
public static void method1(int num1, int num2, int num3, int num4, int num5) {
}
}
注意事項
1.一個方法只能有一個可變引數
2.如果方法中有多個引數,可變引數要放到最後。
應用場景: Collections
在Collections中也提供了新增一些元素方法:
public static <T> boolean addAll(Collection<T> c, T... elements)
:往集合中新增一些元素。
程式碼演示:
public class CollectionsDemo {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<Integer>();
//原來寫法
//list.add(12);
//list.add(14);
//list.add(15);
//list.add(1000);
//採用工具類 完成 往集合中新增元素
Collections.addAll(list, 5, 222, 1,2);
System.out.println(list);
}
第二章 Set介面
知識點--Set介面介紹
目標
- Set介面介紹
路徑
- Set介面
講解
Set介面:也稱Set集合,但凡是實現了Set介面的類都叫做Set集合
特點:元素無索引,元素存取無序,元素不可重複(唯一)
實現類:
HashSet集合:元素無索引,元素存取無序,元素不可重複(唯一)
LinkedHashSet集合:元素無索引,元素存取有序,元素不可重複(唯一)
TreeSet集合:元素無索引,元素存取無序,元素不可重複(唯一),元素可排序
注意:
1.Set集合並沒有特有的功能,都是使用Collection父介面中的方法
2.Set集合元素無索引,所以遍歷方式只能是:迭代器,增強for迴圈
知識點--HashSet集合
目標
- 能夠說出HashSet集合的特點
路徑
- HashSet集合的特點
講解
java.util.HashSet
是Set
介面的一個實現類,它所儲存的元素是不可重複的,並且元素都是無序的(即存取順序不能保證不一致)。
我們先來使用一下Set集合儲存,看下現象,再進行原理的講解:
public class Test {
public static void main(String[] args) {
/*
HashSet集合的特點:
HashSet集合(類): 儲存資料的資料結構,雜湊表結構,元素唯一,元素無索引,元素存取無序
*/
// 建立一個HashSet集合,限制集合中元素的型別為String型別
HashSet<String> set = new HashSet<>();
// 往集合中新增元素
set.add("nba");
set.add("cba");
set.add("bac");
set.add("abc");
set.add("nba");
System.out.println(set);// [cba, abc, bac, nba]
}
}
知識點--HashSet集合儲存資料的結構(雜湊表)
目標
- 雜湊表底層結構以及HashSet保證元素唯一原理
路徑
- 雜湊表底層結構
- HashSet保證元素唯一原理
講解
雜湊表底層結構
在JDK1.8之前,雜湊表底層採用陣列+連結串列實現,即使用陣列處理衝突,同一hash值的連結串列都儲存在一個數組裡。但是當位於一個桶中的元素較多,即hash值相等的元素較多時,通過key值依次查詢的效率較低。而JDK1.8中,雜湊表儲存採用陣列+連結串列+紅黑樹實現,當連結串列長度超過閾值(8)時,將連結串列轉換為紅黑樹,這樣大大減少了查詢時間。
簡單的來說,雜湊表是由陣列+連結串列+紅黑樹(JDK1.8增加了紅黑樹部分)實現的,如下圖所示。
HashSet保證元素唯一原理
HashSet集合保證元素唯一的原理:底層是雜湊表結構,雜湊表保證元素唯一依賴於hashCode()和equals方法();
1.當HashSet集合儲存元素的時候,就會呼叫該元素的hashCode()方法計算雜湊值
2.判斷該雜湊值位置上,是否有相同雜湊值的元素
3.如果該雜湊值位置上沒有相同雜湊值的元素,那麼就直接儲存
4.如果該雜湊值位置上有相同雜湊值的元素,那麼就產生了雜湊衝突
5.如果產生了雜湊衝突,就得呼叫該元素的equals()方法與該雜湊值位置上的所有元素進行一一比較:
如果該雜湊值位置上有任意一個元素與該元素相等,那麼就不儲存
如果該雜湊值位置上所有元素與該元素都不相等,那麼就直接儲存
補充:
Object類: hashCode()和equals()方法;
hashCode():Object類中的hashCode()方法是根據地址值計算雜湊值
equals方法():Object類中的equals()方法是比較地址值
public class Demo {
public static void main(String[] args) {
// 建立一個HashSet集合,限制集合中元素的型別為String
HashSet<String> set = new HashSet<>();
// 往集合中新增一些元素
set.add("nba");
set.add("cba");
set.add("bac");
set.add("abc");
set.add("nba");
// 遍歷列印集合
for (String e : set) {
System.out.println(e);// cba abc bac nba
}
System.out.println("nba".hashCode());// nba:108845
System.out.println("cba".hashCode());// cba:98274
System.out.println("bac".hashCode());// bac:97284
System.out.println("abc".hashCode());// abc:96354
}
}
知識點-- HashSet儲存自定義型別元素
1.目標
- 使用HashSet集合儲存自定義元素
2.路徑
- 程式碼演示
3.講解
給HashSet中存放自定義型別元素時,需要重寫物件中的hashCode和equals方法,建立自己的比較方式,才能保證HashSet集合中的物件唯一.
public class Person{
/**
* 姓名
*/
public String name;
/**
* 年齡
*/
public int age;
public Person() {
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age &&
Objects.equals(name, person.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
建立測試類:
public class Demo {
public static void main(String[] args) {
// 建立多個Person物件
Person p1 = new Person("張三", 18);
Person p2 = new Person("李四", 38);
Person p3 = new Person("王五", 28);
Person p4 = new Person("張三", 18);
// 建立HashSet集合物件,限制集合中元素的型別為Person
HashSet<Person> set = new HashSet<>();
// 往集合中新增Person物件
set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);
// 遍歷列印集合中的元素
for (Person p : set) {
System.out.println(p);
}
System.out.println(p1.hashCode());
System.out.println(p2.hashCode());
System.out.println(p3.hashCode());
System.out.println(p4.hashCode());
}
}
知識點-- LinkedHashSet
目標
- 使用LinkedHashSet保證元素怎麼存就怎麼取,即存取有序
路徑
- 程式碼演示
講解
我們知道HashSet保證元素唯一,可是元素存放進去是沒有順序的,那麼我們要保證有序,怎麼辦呢?
在HashSet下面有一個子類java.util.LinkedHashSet
,它是連結串列和雜湊表組合的一個數據儲存結構。
演示程式碼如下:
public class LinkedHashSetDemo {
public static void main(String[] args) {
Set<String> set = new LinkedHashSet<String>();
set.add("bbb");
set.add("aaa");
set.add("abc");
set.add("bbc");
Iterator<String> it = set.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
結果:
bbb
aaa
abc
bbc
知識點-- TreeSet集合
目標
- 知道使用TreeSet集合的特點並能夠使用TreeSet集合
路徑
- 程式碼演示
講解
特點
TreeSet集合是Set介面的一個實現類,底層依賴於TreeMap,是一種基於紅黑樹的實現,其特點為:
- 元素唯一
- 元素沒有索引
- 使用元素的自然順序對元素進行排序,或者根據建立 TreeSet 時提供的
Comparator
比較器
進行排序,具體取決於使用的構造方法:
public TreeSet(): 根據其元素的自然排序進行排序
public TreeSet(Comparator<E> comparator): 根據指定的比較器進行排序
演示
案例演示自然排序(20,18,23,22,17,24,19):
public static void main(String[] args) {
//無參構造,預設使用元素的自然順序進行排序
TreeSet<Integer> set = new TreeSet<Integer>();
set.add(20);
set.add(18);
set.add(23);
set.add(22);
set.add(17);
set.add(24);
set.add(19);
System.out.println(set);
}
控制檯的輸出結果為:
[17, 18, 19, 20, 22, 23, 24]
案例演示比較器排序(20,18,23,22,17,24,19):
public static void main(String[] args) {
//有參構造,傳入比較器,使用比較器對元素進行排序
TreeSet<Integer> set = new TreeSet<Integer>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
//元素前 - 元素後 : 升序
//元素後 - 元素前 : 降序
return o2 - o1;
}
});
set.add(20);
set.add(18);
set.add(23);
set.add(22);
set.add(17);
set.add(24);
set.add(19);
System.out.println(set);
}
控制檯的輸出結果為:
[24, 23, 22, 20, 19, 18, 17]
第三章 Map集合
知識點-- Map概述
目標
- 能夠說出Map集合的特點
路徑
- 圖文演示
講解
Map集合的概述:
Map<K,V>介面概述:也稱Map集合,是所有雙列集合的頂層父介面,K用來限制鍵的型別,V用來限制值的型別
Map集合的特點:
1.Map集合儲存元素是以鍵值對的形式儲存,也就是說每一個鍵值對都有鍵和值
2.通過鍵取值
3.Map集合中的鍵不能重複,如果鍵重複了,那麼值就會覆蓋
4.Map集合中的值是可以重複
Map集合的實現類:
HashMap類:鍵唯一,鍵值對存取無序, 由雜湊表保證鍵唯一
LinkedHashMap類:鍵唯一,鍵值對存取有序,由雜湊表保證鍵唯一,由連結串列保證鍵值對存取有序
TreeMap類:鍵唯一,可以對鍵值對進行排序
知識點-- Map的常用方法
目標
- 使用Map的常用方法
路徑
- 程式碼演示
講解
Map介面中定義了很多方法,常用的如下:
public V put(K key, V value)
: 把指定的鍵與指定的值新增到Map集合中。public V remove(Object key)
: 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。public V get(Object key)
根據指定的鍵,在Map集合中獲取對應的值。public boolean containsKey(Object key)
:判斷該集合中是否有此鍵public Set<K> keySet()
: 獲取Map集合中所有的鍵,儲存到Set集合中。public Collection<V> values()
獲取Map集合中所有的值,儲存到Collection集合中public Set<Map.Entry<K,V>> entrySet()
: 獲取到Map集合中所有的鍵值對物件的集合(Set集合)。
Map介面的方法演示
public class Test {
public static void main(String[] args) {
/*
Map<K,V>的常用方法:
- public V put(K key, V value): 把指定的鍵與指定的值新增到Map集合中。
- public int size() 獲取集合中鍵值對的個數(Map集合的大小)
- public V remove(Object key): 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。
- public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
- public boolean containsKey(Object key):判斷該集合中是否有此鍵
- public boolean containsValue(Object value) 判斷該集合中是否有此值
- public Set<K> keySet(): 獲取Map集合中所有的鍵,儲存到Set集合中。
- public Collection<V> values() 獲取Map集合中所有的值,儲存到Collection集合中。
- public Set<Map.Entry<K,V>> entrySet(): 獲取到Map集合中 所有的 鍵值對物件 的集合(Set集合)。
Entry<K, V>: 一種資料型別,表示鍵值對物件型別
由於 Entry<K, V> 是Map介面的成員內部介面,所以表示的時候這麼寫Map.Entry<K,V>
Entry介面中的方法:
K getKey(); 獲取鍵值對物件的鍵
V getValue(); 獲取鍵值對物件的值
鍵值對: 兩個物件
鍵值對物件: 一個物件(包裝了鍵值對後的一個物件)
*/
Map<String, String> map = new HashMap<>();
// 往集合中新增鍵值對
map.put("黃曉明", "楊穎");
map.put("文章", "馬伊琍");
map.put("謝霆鋒", "王菲");
map.put("李亞鵬", "王菲");
// public Set<Map.Entry<K,V>> entrySet(): 獲取到Map集合中 所有的 鍵值對物件 的集合(Set集合)。
Set<Map.Entry<String, String>> entrySet = map.entrySet();
System.out.println(entrySet);
System.out.println(entrySet.size());
}
/*
- public Set<K> keySet(): 獲取Map集合中所有的鍵,儲存到Set集合中。
- public Collection<V> values() 獲取Map集合中所有的值,儲存到Collection集合中。
*/
private static void method02() {
// 建立Map集合,限制鍵的型別為String,限制值的型別為String
Map<String, String> map = new HashMap<>();
// 往集合中新增鍵值對
map.put("黃曉明", "楊穎");
map.put("文章", "馬伊琍");
map.put("謝霆鋒", "王菲");
map.put("李亞鵬", "王菲");
// public Set<K> keySet(): 獲取Map集合中所有的鍵,儲存到Set集合中。
Set<String> keys = map.keySet();
System.out.println(keys);// [文章, 謝霆鋒, 李亞鵬, 黃曉明]
// public Collection<V> values() 獲取Map集合中所有的值,儲存到Collection集合中。
Collection<String> values = map.values();
System.out.println(values);// [馬伊琍, 王菲, 王菲, 楊穎]
}
/*
- public V put(K key, V value): 把指定的鍵與指定的值新增到Map集合中。
- public int size() 獲取集合中鍵值對的個數(Map集合的大小)
- public V remove(Object key): 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的值。
- public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
- public boolean containsKey(Object key):判斷該集合中是否有此鍵
- public boolean containsValue(Object value) 判斷該集合中是否有此值
*/
private static void method01() {
// 建立Map集合,限制鍵的型別為String,限制值的型別為String
Map<String, String> map = new HashMap<>();
// public V put(K key, V value) 把指定的鍵與指定的值新增到Map集合中。
map.put("黃曉明","楊穎");
String value1 = map.put("文章", "馬伊琍");// null
String value2 = map.put("文章", "姚笛");// 馬伊琍
map.put("謝霆鋒", "王菲");
System.out.println("value1:"+value1);
System.out.println("value2:"+value2);
System.out.println(map);// {文章=姚笛, 謝霆鋒=王菲, 黃曉明=楊穎}
// public int size() 獲取集合中鍵值對的個數(Map集合的大小)
System.out.println(map.size());// 3
System.out.println("=================================");
// public V remove(Object key); 根據指定的鍵,刪除集合中對應的鍵值對
String value3 = map.remove("文章");
System.out.println("value3:"+value3);// 姚笛
System.out.println(map);// {謝霆鋒=王菲, 黃曉明=楊穎}
// public V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值。
String value4 = map.get("謝霆鋒");
System.out.println("value4:"+value4);// 王菲
System.out.println("======================");
// public boolean containKey(Object key):判斷該集合中是否有此鍵
System.out.println(map.containsKey("謝霆鋒"));// true
System.out.println(map.containsKey("李亞鵬"));// false
// public boolean containsValue(Object value) 判斷該集合中是否有此值
System.out.println(map.containsValue("王菲"));// true
System.out.println(map.containsValue("張柏芝"));// false
}
}
tips:
使用put方法時,若指定的鍵(key)在集合中沒有,則沒有這個鍵對應的值,返回null,並把指定的鍵值新增到集合中;
若指定的鍵(key)在集合中存在,則返回值為集合中鍵對應的值(該值為替換前的值),並把指定鍵所對應的值,替換成指定的新值。
知識點--Map的遍歷
目標
- 使用Map的遍歷
路徑
- 方式1:鍵找值方式
- 方式2:鍵值對方式
講解
方式1:鍵找值方式
通過元素中的鍵,獲取鍵所對應的值
分析步驟:
- 獲取Map中所有的鍵,由於鍵是唯一的,所以返回一個Set集合儲存所有的鍵。方法提示:
keyset()
- 遍歷鍵的Set集合,得到每一個鍵。
- 根據鍵,獲取鍵所對應的值。方法提示:
get(K key)
public class Demo {
public static void main(String[] args) {
// 建立Map集合物件,限制鍵的型別為String,值的型別為String
Map<String, String> map = new HashMap<>();
// 往map集合中新增鍵值對
map.put("黃曉明", "楊穎");
map.put("文章", "馬伊琍");
map.put("謝霆鋒", "王菲");
// 遍歷map集合
// 獲取集合中所有的鍵 Set<K> keySet()方法
Set<String> keys = map.keySet();
// 遍歷所有的鍵的集合
for (String key : keys) {
// 在迴圈中,根據鍵找值 V get(K key)方法
String value = map.get(key);
System.out.println("鍵:"+key+",值:"+value);
}
}
}
方式2:鍵值對方式
Entry<K,V>介面:簡稱Entry項,表示鍵值對物件,用來封裝Map集合中的鍵值對
Entry<K,V>介面:是Map介面中的內部介面,在外部使用的時候是這樣表示: Map.Entry<K,V>
Map集合中提供了一個方法來獲取所有鍵值對物件:
public Set<Map.Entry<K,V>> entrySet()
根據鍵值對對物件獲取鍵和值:
- public K getKey():獲取Entry物件中的鍵。
- public V getValue():獲取Entry物件中的值。
Map遍歷方式二:根據鍵值對物件的方式
1.獲取集合中所有鍵值對物件,以Set集合形式返回。 Set<Map.Entry<K,V>> entrySet()
2.遍歷所有鍵值對物件的集合,得到每一個鍵值對(Entry)物件。
3.在迴圈中,可以使用鍵值對對物件獲取鍵和值 getKey()和getValue()
public class Demo {
public static void main(String[] args) {
// 建立Map集合物件,限制鍵的型別為String,值的型別為String
Map<String, String> map = new HashMap<>();
// 往map集合中新增鍵值對
map.put("黃曉明", "楊穎");
map.put("文章", "馬伊琍");
map.put("謝霆鋒", "王菲");
// 獲取集合中所有鍵值對物件 Set<Map.Entry<K,V>> entrySet()
Set<Map.Entry<String, String>> entrySet = map.entrySet();
// 遍歷所有鍵值對物件的集合
for (Map.Entry<String, String> entry : entrySet) {
// 在迴圈中,可以使用鍵值對對物件獲取鍵和值 getKey()和getValue()
String key = entry.getKey();
String value = entry.getValue();
System.out.println("鍵:"+key+",值:"+value);
}
}
}
知識點-- HashMap儲存自定義型別
目標
- 使用HashMap儲存自定義型別
路徑
- 程式碼演示
講解
練習:每位學生(姓名,年齡)都有自己的家庭住址。那麼,既然有對應關係,則將學生物件和家庭住址儲存到map集合中。學生作為鍵, 家庭住址作為值。
注意,學生姓名相同並且年齡相同視為同一名學生。
編寫學生類:
public class Student {
/**
* 姓名
*/
public String name;
/**
* 年齡
*/
public int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
編寫測試類:
public class Demo {
public static void main(String[] args) {
// 建立Map集合,指定鍵的型別為Student,值的型別為String
HashMap<Student,String> map = new HashMap<>();
// 建立多個學生物件
Student stu1 = new Student("張三", 18);
Student stu2 = new Student("李四", 38);
Student stu3 = new Student("王五", 28);
Student stu4 = new Student("張三", 18);
// 把學生物件作為鍵,家庭地址作為值,儲存到map集合中
map.put(stu1,"北京");
map.put(stu2,"上海");
map.put(stu3,"深圳");
map.put(stu4,"廣州");
// 列印map集合
System.out.println(map);
System.out.println(map.size());// 3
}
}
- 當給HashMap中存放自定義物件時,如果自定義物件作為key存在,這時要保證物件唯一,必須複寫物件的hashCode和equals方法(如果忘記,請回顧HashSet存放自定義物件)。
- 如果要保證map中存放的key和取出的順序一致,可以使用
java.util.LinkedHashMap
集合來存放。
知識點--LinkedHashMap介紹
目標
- 我們知道HashMap保證成對元素唯一,並且查詢速度很快,可是成對元素存放進去是沒有順序的,那麼我們要保證有序,還要速度快怎麼辦呢?
路徑
- LinkedHashMap
講解
- 通過連結串列結構可以保證元素的存取順序一致;
- 通過雜湊表結構可以保證的鍵的唯一、不重複,需要重寫鍵的hashCode()方法、equals()方法。
public class Test {
public static void main(String[] args) {
/*
LinkedHashMap介紹:
LinkedHashMap集合(類): 元素無索引,鍵唯一,鍵值對元素存取有序
儲存資料採用的是雜湊表+連結串列結構
由雜湊表保證鍵唯一,由連結串列保證鍵值對元素存取有序
如果鍵是自定義型別的類,為了保證鍵唯一,就得重寫hashCode()和equals()方法
*/
// 建立LinkedHashMap集合,限制鍵的型別為String型別,限制值的型別為String型別
LinkedHashMap<String, String> map = new LinkedHashMap<>();
//HashMap<String, String> map = new HashMap<>();
// 往集合中新增鍵值對
map.put("黃曉明", "楊穎");
map.put("文章", "馬伊琍");
map.put("謝霆鋒", "王菲");
map.put("李亞鵬", "王菲");
map.put("文章", "姚笛");
// 列印集合
System.out.println(map);
}
}
知識點--TreeMap集合
目標
- 使用TreeMap集合
路徑
- TreeMap介紹
- 構造方法
講解
TreeMap介紹
TreeMap集合和Map相比沒有特有的功能,底層的資料結構是紅黑樹;可以對元素的鍵進行排序,排序方式有兩種:自然排序和比較器排序;到時使用的是哪種排序,取決於我們在建立物件的時候所使用的構造方法;
構造方法
public TreeMap() 使用自然排序
public TreeMap(Comparator<? super K> comparator) 通過比較器指定規則排序
案例演示
public class Test {
public static void main(String[] args) {
/*
TreeMap集合:
TreeMap集合(類):元素無索引,鍵唯一,鍵值對元素根據鍵排序
儲存資料採用的是紅黑樹結構,由紅黑樹結構保證鍵唯一
構造方法:
TreeMap(); 按照鍵的預設排序規則對鍵值對進行排序
要求: 集合中鍵所屬的類要實現Comparable介面,重寫compareTo方法,在該方法中寫好預設的排序規則
TreeMap(Comparator<? super K> comparator):按照鍵的指定排序規則對鍵值對進行排序
鍵為自定義型別的類,課後自己去玩玩
*/
// 按照鍵的預設規則排序:
// 建立TreeMap集合,限制鍵的型別為Integer,限制值的型別為String
TreeMap<Integer, String> map = new TreeMap<>();
// 往集合中新增鍵值對
map.put(300, "黃曉明");
map.put(100, "劉德華");
map.put(200, "黎明");
map.put(500, "張學友");
map.put(400, "郭富城");
// 列印集合
System.out.println(map);// {100=劉德華, 200=黎明, 300=黃曉明, 400=郭富城, 500=張學友}
System.out.println("+++++++++++++++++++++++++++++++++");
// 按照鍵的指定規則排序:
// 建立TreeMap集合,限制鍵的型別為Integer,限制值的型別為String
TreeMap<Integer, String> map2 = new TreeMap<>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
// 指定規則: 前減後 升序 後減前 降序
return o2 - o1;
}
});
// 往集合中新增鍵值對
map2.put(300, "黃曉明");
map2.put(100, "劉德華");
map2.put(200, "黎明");
map2.put(500, "張學友");
map2.put(400, "郭富城");
System.out.println(map2);// {500=張學友, 400=郭富城, 300=黃曉明, 200=黎明, 100=劉德華}
}
}
案例-- Map集合練習
需求
- 輸入一個字串,獲取該字串中每個字元出現次數。
分析
- 獲取一個字串物件
- 建立一個Map集合,鍵代表字元,值代表次數。
- 遍歷字串得到每個字元。
- 判斷Map中是否有該鍵。
- 如果沒有,第一次出現,儲存次數為1;如果有,則說明已經出現過,獲取到對應的值進行++,再次儲存。
- 列印最終結果
實現
方法介紹
public boolean containKey(Object key)
:判斷該集合中是否有此鍵。
程式碼:
public class Test {
public static void main(String[] args) {
/*
Map集合練習:
需求:輸入一個字串中每個字元出現次
*/
// 分析:
// 1.建立Map集合,限制鍵的型別為Character,值的型別為Integer
Map<Character, Integer> map = new HashMap<>();
// 2.建立Scanner物件
Scanner sc = new Scanner(System.in);
// 3.獲取鍵盤錄入的字串
System.out.println("請輸入一個字串:");
String str = sc.nextLine();
// 4.遍歷字串的每一個字元
for (int i = 0; i < str.length(); i++) {
// 5.在迴圈中,獲取字串的字元,該字元作為map集合的鍵
char cKey = str.charAt(i);
// 6.在迴圈中,判斷遍歷出來的字元在map集合中是否存在該鍵
boolean flag = map.containsKey(cKey);
// 7.在迴圈中,如果不存在,字元作為鍵,值為1,儲存到map集合中
// 8.在迴圈中,如果存在,獲取該字元鍵對應的值,進行+1後作為新的值
// 然後在重新儲存到集合中
if (flag == false){
map.put(cKey,1);
}else{
Integer oldValue = map.get(cKey);// 獲取該字元鍵對應的值
Integer newValue = oldValue + 1;// +1
map.put(cKey,newValue);
}
}
// 9.最後列印map集合
System.out.println(map);
}
}
第四章 集合的巢狀
- 總述:任何集合內部都可以儲存其它任何集合
知識點--集合的巢狀
目標
- 理解集合的巢狀
路徑
- List巢狀List
- List巢狀Map
- Map巢狀Map
講解
List巢狀List
public class Test1 {
public static void main(String[] args) {
/*
集合的巢狀:
- List巢狀List
- List巢狀Map
- Map巢狀Map
結論:任何集合內部都可以儲存其它任何集合
*/
// List巢狀List
// 建立一個List集合,限制元素型別為String
List<String> list1 = new ArrayList<>();
// 往集合中新增元素
list1.add("王寶強");
list1.add("賈乃亮");
list1.add("陳羽凡");
// 建立一個List集合,限制元素型別為String
List<String> list2 = new ArrayList<>();
// 往集合中新增元素
list2.add("馬蓉");
list2.add("李小璐");
list2.add("白百何");
// 建立一個List集合,限制元素型別為List集合 (List集合中的元素是List集合)
List<List<String>> list = new ArrayList<>();
list.add(list1);
list.add(list2);
// 遍歷
for (List<String> e : list) {
for (String name : e) {
System.out.println(name);
}
System.out.println("=============");
}
System.out.println(list);
}
}
List巢狀Map
public class Test2 {
public static void main(String[] args) {
/*
List巢狀Map:
*/
// 建立Map集合物件
Map<String,String> map1 = new HashMap<>();
map1.put("it001","迪麗熱巴");
map1.put("it002","古力娜扎");
// 建立Map集合物件
Map<String,String> map2 = new HashMap<>();
map2.put("heima001","蔡徐坤");
map2.put("heima002","李易峰");
// 建立List集合,用來儲存以上2個map集合
List<Map<String,String>> list = new ArrayList<>();
list.add(map1);
list.add(map2);
System.out.println(list.size()); // 2
for (Map<String, String> map : list) {
// 遍歷獲取出來的map集合物件
Set<String> keys = map.keySet();// 獲取map集合所有的鍵
// 根據鍵找值
for (String key : keys) {
System.out.println(key + ","+ map.get(key));
}
}
}
}
Map巢狀Map
public class Test3 {
public static void main(String[] args) {
/*
Map巢狀Map:
*/
// 建立Map集合物件
Map<String,String> map1 = new HashMap<>();
map1.put("it001","迪麗熱巴");
map1.put("it002","古力娜扎");
// 建立Map集合物件
Map<String,String> map2 = new HashMap<>();
map2.put("heima001","蔡徐坤");
map2.put("heima002","李易峰");
// 建立Map集合,把以上2個Map集合作為值儲存到這個map集合中
Map<String, Map<String, String>> map = new HashMap<>();
map.put("傳智部落格",map1);
map.put("黑馬程式設計師",map2);
System.out.println(map.size());// 2
// 獲取map集合中的所有鍵
Set<String> keys = map.keySet();
// 遍歷所有的鍵
for (String key : keys) {
// 根據鍵找值
Map<String, String> value = map.get(key);
// 遍歷value這個Map集合
Set<String> keySet = value.keySet();
for (String k : keySet) {
String v = value.get(k);
System.out.println(k+","+v);
}
}
}
}