day09【Map、鬥地主排序、冒泡排序】
反饋和複習
a.比較器口訣: 升序 前-後(源碼)
b.爲什麼保證元素的唯一性.重寫hashCode和equals
因爲Hash表結構,底層就是根據hashCode和equals來判斷兩個元素是否重複
1.Collection: 7+1
2.List: 7+1+4
ArrayList: 7+1+4
LinkedList: 7+1+4+8
3.Set:7+1
HashSet:7+1 無序
LinkedHashSet:7+1 有序
TreeSet:7+1 無序(有自然順序的)
4.Collections
shuffle(List list); 打亂集合順序
sort(List list); 對集合元素進行排序(默認升序)
sort(List list,Comparator 比較器); 自定義排序規則(升序 前-後)
今日內容
1.Map集合(和Collection沒有直接的聯繫)
2.集合的嵌套(集合的元素還是集合)
3.鬥地主發牌案例(必須3遍以上)
4.冒泡排序算法(a.算法過程 b.算法的代碼實現)
第一章 Map集合【重點】
1.1 Map的概述以及其特點
什麼是Map集合:
Collection集合稱爲單列集合,Map集合稱爲雙列集合
Map集合的特點:
a.Collection每個元素單獨存在(單列),Map每個元素成對存在(雙列)
b.Map集合鍵必須是唯一的,值是可以重複的
c.Collection<E>中泛型只有一個,Map<K,V>中泛型有兩個(其中K代表鍵的類型,V代表值的類)
1.2 Map的3個常用實現類以及其特點
Map接口有三個常見的實現類:
HashMap: 底層採用哈希表結構, 無序
LinkedHashMap:底層採用鏈表+哈希表結構,有序
TreeMap: 底層採用紅黑樹結構,無序(但是鍵有自然順序)
重點: Map中爲了保證鍵的唯一性,如果鍵是自定義類型,必須重寫鍵的hashCode和equals方法
1.3 Map接口定義的通用方法【重點】
增: V put(K 鍵,V 值); 添加一個鍵值對,返回null
刪: V remove(K 鍵);根據鍵去刪除鍵值對,返回被刪除的鍵值對的值
改: V put(K 鍵,V 值); 添加一個重複的鍵時,該方法變成修改,返回修改前的值
查: V get(K 鍵); 根據鍵獲取對應的值
其他:
public boolean containsKey(Object 鍵); 判斷Map中是否包含該鍵
public boolean containsValue(Object 值); 判斷Map中是否包含該值
使用Map中通用方法:
public class TestMap {
public static void main(String[] args) {
//1.創建一個Map的實現類對象
HashMap<String,Integer> map = new HashMap<String, Integer>();
//2.添加幾個
map.put("張三",18);
map.put("李四",28);
map.put("王五",38);
map.put("趙六",48);
map.put("前妻",8);
map.put("王八",88);
//3.打印
//{李四=28, 張三=18, 前妻=8, 王五=38, 趙六=48, 王八=88}
System.out.println(map);
//4.刪除
Integer v1 = map.remove("王五");
System.out.println(v1);
System.out.println(map);
//5.獲取
Integer v2 = map.get("張三");
System.out.println(v2);
System.out.println(map);
//6.修改,也是調用put
Integer v3 = map.put("前妻", 9);
System.out.println(v3);
System.out.println(map);
//7.判斷
boolean b1 = map.containsKey("趙七");
System.out.println(b1);
boolean b2 = map.containsValue(18);
System.out.println(b2);
}
}
1.4 Map的遍歷【非常重點】
-
遍歷方式一
第一種方式稱爲:以鍵找值 public class TestMap01 { public static void main(String[] args) { //第一種遍歷方式:以鍵找值 //1.創建一個Map的實現類對象 HashMap<String, Integer> map = new HashMap<String, Integer>(); //2.添加幾個 map.put("張三", 18); map.put("李四", 28); map.put("王五", 38); map.put("趙六", 48); map.put("前妻", 8); map.put("王八", 88); //3.獲取所有的鍵 Set<String> keys = map.keySet(); //4.遍歷這個keys集合 for (String key : keys) { //5.以鍵找值 Integer value = map.get(key); System.out.println(key + "..." + value); } } }
-
遍歷方式二
第二種方式稱爲:鍵值對方式 public class TestMap02 { public static void main(String[] args) { //第一種遍歷方式:以鍵找值 //1.創建一個Map的實現類對象 HashMap<String, Integer> map = new HashMap<String, Integer>(); //2.添加幾個 map.put("張三", 18); map.put("李四", 28); map.put("王五", 38); map.put("趙六", 48); //Map集合遍歷的第二種方式:鍵值對方式 //3.獲取Map中所有的鍵值對 Set<Map.Entry<String, Integer>> entries = map.entrySet(); //4.遍歷這個entries集合 for (Map.Entry<String, Integer> entry : entries) { //5.從entry中取出鍵和值 String key = entry.getKey(); Integer value = entry.getValue(); //6.打印 System.out.println(key+"..."+value); } } }
1.5 HashMap存儲自定義類型的鍵
需求:
創建一個Map,學生作爲鍵, 家庭住址作爲值。
HashMap<Student,String>
public class TestDemo {
public static void main(String[] args) {
//創建一個Map,學生作爲鍵, 家庭住址作爲值。
//1.創建集合
HashMap<Student,String> map = new HashMap<Student, String>();
//2.添加數據
map.put(new Student("jack",12),"北京中關村");
map.put(new Student("rose",16),"南京中關村");
map.put(new Student("marry",20),"天津中關村");
map.put(new Student("tom",12),"東京中關村");
//3.打印
//{Student{name=jack,age=12}="北京中關村",鍵=值,鍵=值,鍵=值}
System.out.println(map);
//4.我要修改rose的地址
map.put(new Student("rose",16),"廣東東莞");
System.out.println(map);
}
}
結論:
如果鍵是自定義類型,爲了保證鍵的唯一性,必須重寫hashCode和equals方法
1.6 LinkedHashMap介紹
HashMap底層採用哈希表結構,是無序的
LinkedHashMap底層採用鏈表+哈希表結構,是有序的
public class TestLinkedHashMap {
public static void main(String[] args) {
//1.創建一個LinkedHashMap
LinkedHashMap<String, Integer> map = new LinkedHashMap<String, Integer>();
//2.添加幾個
map.put("rose",20);
map.put("jack",10);
map.put("marry",40);
map.put("tom",30);
//3.打印
System.out.println(map);
}
}
1.7 TreeMap集合
a.TreeMap底層採用紅黑樹結構
TreeMap也是無序的,會按照鍵的自然順序默認升序
public class TestTreeMap {
public static void main(String[] args) {
//1.創建一個TreeMap集合
TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
//2.添加
treeMap.put(20,"李四");
treeMap.put(30,"王五");
treeMap.put(40,"趙六");
treeMap.put(10,"張三");
//3.打印
System.out.println(treeMap);
}
}
擴展:
如果鍵是數值類型,那麼按照鍵值的大小升序
如果鍵是字符類型,那麼按照鍵的碼值的大小升序
如果鍵是字符串類型,那麼按照鍵的首字母大小升序,如果首字母相同按照次字母,依次類推...
這四種的結論是一樣: Arrays.sort Collections.sort TreeSet TreeMap
b.我們也可以使用比較器排序
使用TreeMap的另外一個構造即可
public TreeMap(Comparator 比較器);
public class TestTreeMap {
public static void main(String[] args) {
//1.創建一個TreeMap集合
// TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>();
TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
//口訣: 升序 前-後
return o2-o1;
}
});
//2.添加
treeMap.put(20,"李四");
treeMap.put(30,"王五");
treeMap.put(40,"趙六");
treeMap.put(10,"張三");
//3.打印
System.out.println(treeMap);
//4.創建TreeMap集合,鍵是自定義類型
TreeMap<Student, String> map = new TreeMap<Student,String>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
//按照年齡降序
// return o2.age-o1.age;
//按照姓名的長度升序
return o1.name.length()-o2.name.length();
}
});
//5.添加數據
map.put(new Student("jack",20),"北京");
map.put(new Student("ady",10),"南京");
map.put(new Student("marry",8),"東京");
map.put(new Student("hanmeimei",15),"西京");
//6.打印
System.out.println(map);
}
}
1.8 Map集合練習【重點】
面試題:
輸入一個字符串中每個字符出現次數。
public class TestDemo {
public static void main(String[] args) {
//輸入一個字符串中每個字符出現次數。
//分析:
//最後的結果是什麼樣?? a=3 b=2 c=10 d=5
//1.定義一個map
LinkedHashMap<Character,Integer> map = new LinkedHashMap<Character, Integer>();
//2.輸入一個字符串
System.out.println("請輸入一個字符串:");
String str = new Scanner(System.in).nextLine();
//abcdabcdac
//3.遍歷字符串
for (int i = 0; i < str.length(); i++) {
//4.取出字符串中的某個字符
char ch = str.charAt(i);
//5.這個字符ch以前出現過
if (map.containsKey(ch)){
Integer oldCount = map.get(ch);
map.put(ch,oldCount+1);
}else{
//5.這個字符ch以前沒出現過
map.put(ch,1);
}
}
//4.打印結果 map
System.out.println(map);
}
}
第二章 集合的嵌套【難點&重點】
什麼是集合的嵌套
集合中的元素還是一個集合
2.1 List嵌套List
a.使用List集合保證兩個班的學生名字
public class TestListList {
public static void main(String[] args) {
//a.使用List集合保證兩個班的學生名字
//1.創建集合保存一個班級學生
ArrayList<String> ban1 = new ArrayList<String>();
ban1.add("jack");
ban1.add("rose");
ban1.add("tom");
//2.創建集合保存一個班級學生
ArrayList<String> ban2 = new ArrayList<String>();
ban2.add("小花");
ban2.add("小草");
ban2.add("小狗");
//3.將ban1和ban2兩個集合,保存到一個大集合中
ArrayList<ArrayList<String>> bans = new ArrayList<>();
bans.add(ban1);
bans.add(ban2);
//4.自己遍歷
for (ArrayList<String> ban : bans) {
for (String name : ban) {
System.out.println(name);
}
}
//5.直接打印
// System.out.println(bans);//[[],[]]
}
}
2.2 List嵌套Map
a.保存兩個班學生的名字以及對應的年齡
public class TestListMap {
public static void main(String[] args) {
//a.保存兩個班學生的名字以及對應的年齡
//1.保存第一個班級學生的姓名和年齡
HashMap<String, Integer> map1 = new HashMap<String, Integer>();
map1.put("jack",12);
map1.put("rose",11);
map1.put("tom",10);
//2.保存第二個班級學生的姓名和年齡
HashMap<String, Integer> map2 = new HashMap<String, Integer>();
map2.put("張鵬",18);
map2.put("徐睿",19);
map2.put("張亭",17);
//3.創建一個大集合 保存兩個map
ArrayList<HashMap<String, Integer>> maps = new ArrayList<HashMap<String, Integer>>();
maps.add(map1);
maps.add(map2);
//4.直接打印
System.out.println(maps); //[{},{}]
//5.自己遍歷
for (HashMap<String, Integer> map : maps) {
Set<String> keys = map.keySet();
for (String key : keys) {
Integer value = map.get(key);
System.out.println(key+".."+value);
}
}
}
}
2.3 Map嵌套Map
a.保證兩個班的名字和班裏同學的姓名以及對應的年齡
public class TestMapMap {
public static void main(String[] args) {
//a.保證兩個班的名字和班裏同學的姓名以及對應的年齡
//1.保存第一個班級同學的姓名和年齡
HashMap<String, Integer> map1 = new HashMap<String, Integer>();
map1.put("jack",12);
map1.put("rose",11);
map1.put("tom",10);
//2.保存第二個班級同學的姓名和年齡
HashMap<String, Integer> map2 = new HashMap<String, Integer>();
map2.put("張鵬",18);
map2.put("徐睿",19);
map2.put("張亭",17);
//3.將兩個班級的map集合,保存到另外一個集合中,要求有該班級的名字
HashMap<String,HashMap<String, Integer>> all = new HashMap<String, HashMap<String, Integer>>();
all.put("一班",map1);
all.put("二班",map2);
//4.直接打印
System.out.println(all);// {"一班"={jack=12,rose=11,tom=10},鍵=值}
//5.手動遍歷
//1.獲取所有的鍵
Set<String> names = all.keySet();
//2.遍歷所有的鍵
for (String name : names) {
//3.以鍵找值
HashMap<String, Integer> map = all.get(name);
//4.獲取該map所有的鍵
Set<String> ns = map.keySet();
//5.遍歷ns
for (String n : ns) {
//6.以鍵找值
Integer value = map.get(n);
System.out.println(n+"..."+value);
}
}
}
}
第三章 模擬鬥地主洗牌發牌【重點,至少3遍】
3.1 案例介紹
需求: 模擬鬥地主發牌,看牌(但是不打牌)
3.2 案例分析
步驟分析:
1.準備 編號和牌 組成的Map集合
2.準備一副牌(54個編號)
3.洗牌(打亂集合)
4.發牌(遍歷集合)
5.排序(sort方法)
6.轉牌(以鍵找值)
7.打印給用戶看
3.3 代碼實現
public class TestDouDiZhu {
public static void main(String[] args) {
//1.準備 編號和牌 組成的Map集合
LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>();
//a.花色 4種
String[] colors = {"♠", "♥", "♣", "♦"};
//b.數值 13種
String[] nums = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
//c.編號變量
int id = 1;
//d.組合牌
for (String num : nums) {
for (String color : colors) {
String card = color + num;
//保存到map集合中
map.put(id, card);
id++;
}
}
//e.單獨添加大小王
map.put(53, "小S");
map.put(54, "大S");
//2.準備一副牌(54個編號)
ArrayList<Integer> cards = new ArrayList<Integer>();
for (int i = 1; i < 55; i++) {
cards.add(i);
}
//3.洗牌(打亂集合)
Collections.shuffle(cards);
//4.發牌(遍歷集合)
ArrayList<Integer> player1 = new ArrayList<Integer>();
ArrayList<Integer> player2 = new ArrayList<Integer>();
ArrayList<Integer> player3 = new ArrayList<Integer>();
ArrayList<Integer> diPai = new ArrayList<Integer>();
//遍歷集合
//此處不能使用增強for
for (int i = 0; i < cards.size() - 3; i++) {
//取出每一張牌
Integer card = cards.get(i);
//給誰呢?????????????????????????????????
//i = 0 3 6 p1
//i = 1 4 7 p2
//i = 2 5 8 p3
if (i % 3 == 0) {
player1.add(card);
} else if (i % 3 == 1) {
player2.add(card);
}else{
player3.add(card);
}
}
//最後張三留給底牌
diPai.add(cards.get(53));
diPai.add(cards.get(52));
diPai.add(cards.get(51));
//5.排序(sort方法)
Collections.sort(player1);
Collections.sort(player2);
Collections.sort(player3);
Collections.sort(diPai);
//6.看牌
lookCards(player1,map);
lookCards(player2,map);
lookCards(player3,map);
lookCards(diPai,map);
}
//看牌方法
public static void lookCards(ArrayList<Integer> idCards, LinkedHashMap<Integer, String> map) {
//遍歷
for (Integer idCard : idCards) {
String card = map.get(idCard);
System.out.print(card+" ");
}
System.out.println();
}
}
第四章 冒泡排序算法【理解】
4.1 冒泡排序的介紹
所有冒泡排序的思想是這樣的:
依次比較數組中相連的兩元素,然後將較大元素放在後面,最後按照從小到大順序排列出來
規律:
n個數比較,一共需要比較n-1輪
第1輪,需要比較n-1次,以後每輪比較的次數會遞減
4.2 過程圖解(見圖解)
4.3 代碼實現
冒泡排序算法:
public class TestBubbleSort {
public static void main(String[] args) {
//準備一個數組
int[] arr = {4, 6, 1, 3, 8, 2, 9, 7, 5};
//排序
//一共需要幾輪??? arr.length - 1輪
//外層循環,控制輪數
for(int i = 0;i < arr.length - 1;i++) {
// i = 0 1 2
//內存循環,控制比較的次數
for(int j = 0;j < arr.length - 1 - i;j++){
//比較的兩個元素:
if (arr[j] > arr[j+1]){ //前100 > 後10
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
//測試一下
System.out.println(Arrays.toString(arr));
}
}
總結
1.Map接口定義的共性方法【必須掌握】
put(鍵,值);
remove(鍵);
put(重複的鍵,值);
get(鍵)
containsKey(鍵);
containsValue(值);
2.Map各種實現類的遍歷方式(a.以鍵找值 b.鍵值對方式)【必須掌握】
a.以鍵找值
Set<K> keys = map.keySet(); //獲取所有鍵的集合
for(K key : keys){ //遍歷所有的鍵
V value = map.get(key)//以鍵找值
//打印
sout(key,value);
}
b.鍵值對方式
Set<Map.Entry<K,V>> entrys = map.entrySet();//獲取所有的鍵值對的集合
for(Map.Entry<K,V> entry : entrys){//遍歷這個鍵值對集合
K key = entry.getKey();//獲取鍵值對中的鍵和值
V value = entry.getValue();//獲取鍵值對中的鍵和值
//打印
sout(key,value);
}
3.集合嵌套【難點,開發中見的不多】
a。List套List:
ArrayList<ArrayList<String>> arr;
b。List套Map
ArrayList<HashMap<String,Integer>> map
c。Map套Map
HashMap<String,HashMap<String,Integer>> map
4.鬥地主牌【必須掌握】
至少3遍!!!
5.冒泡排序【理解】
a。理解冒泡過程
b。算法背下來
for(int i = 0;i<arr.length-1;i++){
for(int j = 0;j<arr.length-1-i;j++){
if(arr[j]>arr[j+1]){
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}