傳智黑馬java基礎學習——day20(集合Map)
第20天 集合
- Map介面
- 1Map介面概述
我們通過檢視Map介面描述,發現Map介面下的集合與Collection介面下的集合,它們儲存資料的形式不同,如下圖。
- Collection中的集合,元素是孤立存在的(理解為單身),向集合中儲存元素採用一個個元素的方式儲存。
- Map中的集合,元素是成對存在的(理解為夫妻)。每個元素由鍵與值兩部分組成,通過鍵可以找對所對應的值。
- Collection中的集合稱為單列集合,Map中的集合稱為雙列集合。
- 需要注意的是,Map中的集合不能包含重複的鍵,值可以重複;每個鍵只能對應一個值。
- Map中常用的集合為HashMap集合、LinkedHashMap集合。
1.2Map介面中常用集合概述
通過檢視Map介面描述,看到Map有多個子類,這裡我們主要講解常用的HashMap集合、LinkedHashMap集合。
- HashMap<K,V>:儲存資料採用的雜湊表結構,元素的存取順序不能保證一致。由於要保證鍵的唯一、不重複,需要重寫鍵的hashCode()方法、equals()方法。
- LinkedHashMap<K,V>:HashMap下有個子類LinkedHashMap,儲存資料採用的雜湊表結構+連結串列結構。通過連結串列結構可以保證元素的存取順序一致;通過雜湊表結構可以保證的鍵的唯一、不重複,需要重寫鍵的hashCode()方法、equals()方法。
- 注意:Map介面中的集合都有兩個泛型變數<K,V>,在使用時,要為兩個泛型變數賦予資料型別。兩個泛型變數<K,V>的資料型別可以相同,也可以不同。
1.3Map介面中的常用方法
- put方法:將指定的鍵與值對應起來,並新增到集合中
- 方法返回值為鍵所對應的值
使用put方法時,若指定的鍵(key)在集合中沒有,則沒有這個鍵對應的值,返回null,並把指定的鍵值新增到集合中;
使用put方法時,若指定的鍵(key)在集合中存在,則返回值為集合中鍵對應的值(該值為替換前的值),並把指定鍵所對應的值,替換成指定的新值。
- get方法:獲取指定鍵(key)所對應的值(value)
- remove方法:根據指定的鍵(key)刪除元素,返回被刪除元素的值(value)。
Map介面的方法演示
public class MapDemo {
public static void main(String[] args) {
//建立Map物件
Map<String, String> map = new HashMap<String,String>();
//給map中新增元素
map.put("星期一", "Monday");
map.put("星期日", "Sunday");
System.out.println(map); // {星期日=Sunday, 星期一=Monday}
//當給Map中新增元素,會返回key對應的原來的value值,若key沒有對應的值,返回null
System.out.println(map.put("星期一", "Mon")); // Monday
System.out.println(map); // {星期日=Sunday, 星期一=Mon}
//根據指定的key獲取對應的value
String en = map.get("星期日");
System.out.println(en); // Sunday
//根據key刪除元素,會返回key對應的value值
String value = map.remove("星期日");
System.out.println(value); // Sunday
System.out.println(map); // {星期一=Mon}
}
}
1.4Map集合遍歷鍵找值方式
鍵找值方式:即通過元素中的鍵,獲取鍵所對應的值
操作步驟與圖解:
1.獲取Map集合中所有的鍵,由於鍵是唯一的,所以返回一個Set集合儲存所有的鍵
2.遍歷鍵的Set集合,得到每一個鍵
3.根據鍵,獲取鍵所對應的值
程式碼演示:
public class MapDemo {
public static void main(String[] args) {
//建立Map物件
Map<String, String> map = new HashMap<String,String>();
//給map中新增元素
map.put("鄧超", "孫儷");
map.put("李晨", "范冰冰");
map.put("劉德華", "柳巖");
//獲取Map中的所有key
Set<String> keySet = map.keySet();
//遍歷存放所有key的Set集合
Iterator<String> it =keySet.iterator();
while(it.hasNext()){
//得到每一個key
String key = it.next();
//通過key獲取對應的value
String value = map.get(key);
System.out.println(key+"="+value);
}
}
}
1.5Entry鍵值對物件
在Map類設計時,提供了一個巢狀介面:Entry。Entry將鍵值對的對應關係封裝成了物件。即鍵值對物件,這樣我們在遍歷Map集合時,就可以從每一個鍵值對(Entry)物件中獲取對應的鍵與對應的值。
- Entry是Map介面中提供的一個靜態內部巢狀介面。
- getKey()方法:獲取Entry物件中的鍵
- getValue()方法:獲取Entry物件中的值
- entrySet()方法:用於返回Map集合中所有的鍵值對(Entry)物件,以Set集合形式返回。
1.6Map集合遍歷鍵值對方式
鍵值對方式:即通過集合中每個鍵值對(Entry)物件,獲取鍵值對(Entry)物件中的鍵與值。
操作步驟與圖解:
1.獲取Map集合中,所有的鍵值對(Entry)物件,以Set集合形式返回。
2.遍歷包含鍵值對(Entry)物件的Set集合,得到每一個鍵值對(Entry)物件
3.通過鍵值對(Entry)物件,獲取Entry物件中的鍵與值。
public class MapDemo {
public static void main(String[] args) {
//建立Map物件
Map<String, String> map = new HashMap<String,String>();
//給map中新增元素
map.put("鄧超", "孫儷");
map.put("李晨", "范冰冰");
map.put("劉德華", "柳巖");
//獲取Map中的所有key與value的對應關係
Set<Map.Entry<String,String>> entrySet = map.entrySet();
//遍歷Set集合
Iterator<Map.Entry<String,String>> it =entrySet.iterator();
while(it.hasNext()){
//得到每一對對應關係
Map.Entry<String,String> entry = it.next();
//通過每一對對應關係獲取對應的key
String key = entry.getKey();
//通過每一對對應關係獲取對應的value
String value = entry.getValue();
System.out.println(key+"="+value);
}
}
}
注意:Map集合不能直接使用迭代器或者foreach進行遍歷。但是轉成Set之後就可以使用了。
1.7HashMap儲存自定義型別鍵值
練習:每位學生(姓名,年齡)都有自己的家庭住址。那麼,既然有對應關係,則將學生物件和家庭住址儲存到map集合中。學生作為鍵, 家庭住址作為值。
注意,學生姓名相同並且年齡相同視為同一名學生。
- 學生類
public class Student {
private String name;
private int age;
//編寫構造方法,文件中已省略
//編寫get,set方法,文件中已省略
//編寫toString方法,文件中已省略
}
- 測試類
public class HashMapTest {
public static void main(String[] args) {
//1,建立hashmap集合物件。
Map<Student,String> map = new HashMap<Student,String>();
//2,新增元素。
map.put(new Student("lisi",28), "上海");
map.put(new Student("wangwu",22), "北京");
map.put(new Student("zhaoliu",24), "成都");
map.put(new Student("zhouqi",25), "廣州");
map.put(new Student("wangwu",22), "南京");
//3,取出元素。鍵找值方式
Set<Student> keySet = map.keySet();
for(Student key : keySet){
String value = map.get(key);
System.out.println(key.toString()+"....."+value);
}
//取出元素。鍵值對方式
Set<Map.Entry<Student, String>> entrySet = map.entrySet();
for (Map.Entry<Student, String> entry : entrySet) {
Student key = entry.getKey();
String value = entry.getValue();
System.out.println(key.toString()+"....."+value);
}
}
}
- 當給HashMap中存放自定義物件時,如果自定義物件作為key存在,這時要保證物件唯一,必須複寫物件的hashCode和equals方法(如果忘記,請回顧HashSet存放自定義物件)。
- 如果要保證map中存放的key和取出的順序一致,可以使用LinkedHashMap集合來存放。
1.8靜態匯入
在導包的過程中我們可以直接匯入靜態部分,這樣某個類的靜態成員就可以直接使用了。在原始碼中經常會出現靜態匯入。
靜態匯入格式:
import static XXX.YYY; 匯入後YYY可直接使用。
例如:Map.Entry的訪問,簡化後為Entry
import static java.util.Map.Entry;
public class HashMapTest {
public static void main(String[] args) {
//1,建立hashmap集合物件。
Map<Student,String> map = new HashMap<Student,String>();
//取出元素。鍵值對方式
//Set<Map.Entry<Student, String>> entrySet = map.entrySet();
Set<Entry<Student, String>> entrySet = map.entrySet();
//for (Map.Entry<Student, String> entry : entrySet) {
for (Entry<Student, String> entry : entrySet) {
Student key = entry.getKey();
String value = entry.getValue();
System.out.println(key.toString()+"....."+value);
}
}
}
1.9可變引數
在JDK1.5之後,如果我們定義一個方法需要接受多個引數,並且多個引數型別一致,我們可以對其簡化成如下格式:
修飾符 返回值型別 方法名(引數型別... 形參名){ }
其實這個書寫完全等價與
修飾符 返回值型別 方法名(引數型別[] 形參名){ }
只是後面這種定義,在呼叫時必須傳遞陣列,而前者可以直接傳遞資料即可。
jdk1.5以後。出現了簡化操作。... 用在引數上,稱之為可變引數。
同樣是代表陣列,但是在呼叫這個帶有可變引數的方法時,不用建立陣列(這就是簡單之處),直接將陣列中的元素作為實際引數進行傳遞,其實編譯成的class檔案,將這些元素先封裝到一個陣列中,在進行傳遞。這些動作都在編譯.class檔案時,自動完成了。
程式碼演示:
public class ParamDemo {
public static void main(String[] args) {
int[] arr = {21,89,32};
int sum = add(arr);
System.out.println(sum);
sum = add(21,89,32);//可變引數呼叫形式
System.out.println(sum);
}
//JDK1.5之後寫法
public static int add(int...arr){
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
//原始寫法
/*
public static int add(int[] arr) {
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
return sum;
}
*/
}
- 上述add方法在同一個類中,只能存在一個。因為會發生呼叫的不確定性
注意:如果在方法書寫時,這個方法擁有多引數,引數中包含可變引數,可變引數一定要寫在引數列表的末尾位置。
1.10Collections集合工具類
Collections是集合工具類,用來對集合進行操作。部分方法如下:
- public static <T> void sort(List<T> list) // 集合元素排序
//排序前元素list集合元素 [33,11,77,55]
Collections.sort( list );
//排序後元素list集合元素 [11,33,55,77]
- public static void shuffle(List<?> list) // 集合元素儲存位置打亂
//list集合元素 [11,33,55,77]
Collections.shuffle( list );
//使用shuffle方法後,集合中的元素為[77,33,11,55],每次執行該方法,集合中儲存的元素位置都會隨機打亂
1.11集合巢狀
集合巢狀並不是一個新的知識點,僅僅是集合內容又是集合,如Collection集合巢狀、Collection集合與Map集合相互巢狀、Map集合巢狀。
- ArrayList巢狀 ArrayList
ArrayList< ArrayList<String> >
Collection< ArrayList<Integer> >
- Map巢狀 ArrayList
HashMap<String, ArrayList<Person>>
ArrayList< HashMap<String, String>>
- Map集合巢狀
HashMap<String, HashMap<String,String>>
HashMap<String, HashMap<Person,String>>
1.12集合繼承體系的物件導向思想
- 介面:用來明確所有集合中該具有的功能,相當於在定義集合功能標準;
- 抽象類:把多個集合中功能實現方式相同的方法,抽取到抽象類實現,具體集合不再遍寫,繼承使用即可;
- 具體類:繼承抽象類,實現介面,重寫所有抽象方法,達到具備指定功能的集合。每個具體集合類,根據自身的資料儲存結構方式,對介面中的功能方法,進行不同方式的實現。2
2.模擬鬥地主洗牌發牌
2.1案例介紹
按照鬥地主的規則,完成洗牌發牌的動作。
具體規則:
1. 組裝54張撲克牌
2. 將54張牌順序打亂
3. 三個玩家參與遊戲,三人交替摸牌,每人17張牌,最後三張留作底牌。
4. 檢視三人各自手中的牌(按照牌的大小排序)、底牌
- 手中撲克牌從大到小的擺放順序:大王,小王,2,A,K,Q,J,10,9,8,7,6,5,4,3
2.2案例需求分析
- 準備牌:
完成數字與紙牌的對映關係:
使用雙列Map(HashMap)集合,完成一個數字與字串紙牌的對應關係(相當於一個字典)。
- 洗牌:
通過數字完成洗牌發牌
- 發牌:
將每個人以及底牌設計為ArrayList<String>,將最後3張牌直接存放於底牌,剩餘牌通過對3取模依次發牌。
存放的過程中要求數字大小與鬥地主規則的大小對應。
將代表不同紙牌的數字分配給不同的玩家與底牌。
- 看牌:
通過Map集合找到對應字元展示。
通過查詢紙牌與數字的對應關係,由數字轉成紙牌字串再進行展示。
2.3實現程式碼步驟
首先,要修改java檔案編碼,由GBK修改為UTF-8,因為預設的字元編碼GBK沒有我們要的梅花、方片、黑桃、紅桃(♠♥♦♣)等特殊字元。
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
/*
* 鬥地主洗牌發牌排序
*/
public class Poker {
public static void main(String[] args) {
//準備花色
ArrayList<String> color = new ArrayList<String>();
color.add("♠");
color.add("♥");
color.add("♦");
color.add("♣");
//準備數字
ArrayList<String> number = new ArrayList<String>();
Collections.addAll(number,"3","4","5","6","7","8","9","10","J","Q","K","A","2");
//定義一個map集合:用來將數字與每一張牌進行對應
HashMap<Integer, String> map = new HashMap<Integer, String>();
int index = 0;
for (String thisNumber : number) {
for (String thisColor : color) {
map.put(index++, thisColor+thisNumber);
}
}
//加入大小王
map.put(index++, "小☺");
map.put(index++, "大☻");
//一副54張的牌 ArrayList裡邊為0-53的數的新牌
ArrayList<Integer> cards = new ArrayList<Integer>();
for (int i = 0; i <= 53; i++) {
cards.add(i);
}
//洗牌
Collections.shuffle(cards);
//建立三個玩家和底牌
ArrayList<Integer> iPlayer = new ArrayList<Integer>();
ArrayList<Integer> iPlayer2 = new ArrayList<Integer>();
ArrayList<Integer> iPlayer3 = new ArrayList<Integer>();
ArrayList<Integer> itCards = new ArrayList<Integer>();
//遍歷這副洗好的牌,遍歷過程中,將牌發到三個玩家和底牌中
for (int i = 0; i < cards.size(); i++) {
if(i>=51) {
iCards.add(cards.get(i));
} else {
if(i%3==0) {
iPlayer.add(cards.get(i));
}else if(i%3==1) {
iPlayer2.add(cards.get(i));
}else {
iPlayer3.add(cards.get(i));
}
}
}
//對每個人手中的牌排序
Collections.sort(iPlayer);
Collections.sort(iPlayer2);
Collections.sort(iPlayer3);
//對應數字形式的每個人手中的牌,定義字串形式的牌
ArrayList<String> sPlayer = new ArrayList<String>();
ArrayList<String> sPlayer2 = new ArrayList<String>();
ArrayList<String> sPlayer3 = new ArrayList<String>();
ArrayList<String> sCards = new ArrayList<String>();
for (Integer key : iPlayer) {
sPlayer.add(map.get(key));
}
for (Integer key : iPlayer2) {
sPlayer2.add(map.get(key));
}
for (Integer key : iPlayer3) {
sPlayer3.add(map.get(key));
}
for (Integer key : iCards) {
sCards.add(map.get(key));
}
//看牌
System.out.println(sPlayer);
System.out.println(sPlayer2);
System.out.println(sPlayer3);
System.out.println(sCards);
}
}
- 總結
- 知識點總結
- Map集合:
map集合中的元素都是成對出現,成對儲存的
map集合中的元素都是以一對鍵和值的形式組成存在的,稱為鍵值對,理解為夫妻對
map集合中的鍵不能重複儲存,值可以重複
map集合中的每一個鍵 對應著一個值
- 方法:
V put(K key, V value) 把指定的鍵與指定的值新增到Map集合中
V remove(Object key) 把指定的鍵 所對應的鍵值對元素 在Map集合中刪除,返回被刪除元素的值
Set<Map.Entry<K,V>> entrySet() 獲取到Map集合中所有的鍵值對物件的集合(Set集合)
V get(Object key) 根據指定的鍵,在Map集合中獲取對應的值
Set<K> keySet() 獲取Map集合中所有的鍵,儲存到Set集合中
- Map集合遍歷的兩種方式
- 方式1:根據鍵找值的方式
//a, 獲取到Map集合中所有的鍵,返回對應的Set集合
//b, 遍歷鍵的集合,獲取到每一個鍵
//c, 通過鍵,找到對應的值
//獲取到Map集合中所有的鍵,返回對應的Set集合
Set<String> keys = map.keySet();
//遍歷鍵的集合,獲取到每一個鍵
for (String key : keys) {
//通過鍵,找到對應的值
Student s = map.get(key);
System.out.println( key + "..." + s.getName() + "..." + s.getAge() );
}
- 方式2:根據鍵值對物件找鍵和值的方式
//a, 獲取Map集合中所有的鍵值對元素,返回對應的Set集合
//b, 遍歷鍵值對元素集合,獲取到每一個鍵值對元素物件
//c, 通過鍵值對元素物件,獲取對應的鍵,和對應的值
//獲取Map集合中所有的鍵值對元素,返回對應的Set集合
Set< Map.Entry<String, Student>> entrySet = map.entrySet();
//遍歷鍵值對元素集合,獲取到每一個鍵值對元素物件
for (Map.Entry<String, Student> entry : entrySet) {
//通過鍵值對元素物件,獲取對應的鍵,和對應的值
//找鍵
String key = entry.getKey();
//找值
Student s = entry.getValue();
//列印
System.out.println( key+"..."+s.getName()+"..."+s.getAge() );
}
- HashMap:
- 特點:
是Map集合的子集合
底層採用雜湊表結構
HashMap集合中的key不能重複,通過重寫hashCode() 與 equals()方法來保證鍵的唯一。
不能保證元素存與取的順序完全一致
- LinkedHashMap:
- 特點:
是HashMap集合的子集合
底層採用雜湊表+連結串列結構
LinkedHashMap集合中的key不能重複,通過重寫hashCode() 與 equals()方法來保證鍵的唯一。
- Collections中的方法:
public static <T> void sort(List<T> list) 排序
public static void shuffle(List<?> list) 集合中的元素儲存位置隨機打亂
相關文章
- 傳智黑馬java基礎學習——day19(集合list、Set)Java
- 傳智黑馬java基礎學習——day24Java
- 傳智黑馬java基礎學習——day25Java
- 傳智黑馬java基礎學習——day26Java
- 傳智黑馬java基礎學習——day27Java
- 傳智黑馬java基礎學習——day28Java
- 傳智黑馬java基礎學習——day29Java
- 傳智黑馬java基礎學習——day30Java
- 傳智黑馬java基礎學習——day31Java
- 傳智黑馬java基礎學習——day32Java
- 傳智黑馬java基礎學習——day33Java
- 傳智黑馬java基礎學習——day18Java
- 傳智黑馬java基礎學習——day21(異常)Java
- 傳智黑馬java基礎學習——day22(File、遞迴)Java遞迴
- 傳智黑馬python基礎學習——day14Python
- 傳智黑馬python基礎學習——day01Python
- 傳智黑馬python基礎學習——day02Python
- 傳智黑馬python基礎學習——day03Python
- 傳智黑馬python基礎學習——day04Python
- 傳智黑馬python基礎學習——day05Python
- 傳智黑馬python基礎學習——day06Python
- 傳智黑馬python基礎學習——day07Python
- 傳智黑馬python基礎學習——day08Python
- 傳智黑馬python基礎學習——day09Python
- 傳智黑馬python基礎學習——day10Python
- 傳智黑馬python基礎學習——day11Python
- 傳智黑馬java基礎學習——day23(位元組流、字元流)Java字元
- 傳智黑馬java基礎學習——day17(包裝類、System、Math、Arrays、大資料運算)Java大資料
- Map集合(Java基礎、skycto JEEditor)Java
- 黑馬java基礎學習筆記第一天Java筆記
- Java Map集合練習Java
- Java中的Map集合學習筆記Java筆記
- 黑馬pink JavaScript學習筆記_JS基礎 Day5JavaScript筆記JS
- 傳智播客2018年python基礎班就業班人工智慧深度學習機器學習黑馬15期Python就業班全套培訓教程Python就業人工智慧深度學習機器學習
- Java 13天基礎 06天map集合小練習(黑馬程式設計師) 統計字串中每個字元出現的次數 (經典面試題)Java程式設計師字串字元面試題
- JAVA集合——Map介面Java
- Java集合類——MapJava
- Java基礎 —— 集合(二)Java