Day15

一. Map集合

  1. 定義

    • Map集合是一個(gè)雙列集合,以鍵值對(duì)的形式存在
    • 將鍵和值捆綁到一起存放(Map.Entry)
    • 一個(gè)映射不能包含重復(fù)的鍵
    • 如果出現(xiàn)相同的鍵,會(huì)用新的值覆蓋老的值
    • 每個(gè)鍵最多只能映射到一個(gè)值
  2. Map接口和Collection接口的不同

    • Map是雙列的,Collection是單列的
    • Map集合的數(shù)據(jù)結(jié)構(gòu)針對(duì)鍵有效, 跟值無關(guān), Collection 集合的數(shù)據(jù)結(jié)構(gòu)是針對(duì)元素有效
  3. 常用功能

    • 添加方法
      • V put(K key , V value): 添加元素
        • 如果鍵是第一次存儲(chǔ), 直接存儲(chǔ)元素,返回null
        • 如果鍵不是第一個(gè)存在, 就用值把以前的值替換掉,返回以前的值
    • 刪除方法
      • void clear() : 移除所有的鍵值對(duì)元素
      • V remove(Object key) : 根據(jù)鍵刪除鍵值對(duì)元素, 并把值返回
    • 判斷方法
      • boolean containsKey(Object key) : 判斷集合是否包含指定的鍵
      • boolean containsValue(Object value): 判斷集合是否包含指定的值
      • boolean isEmpty: 判斷集合是否為空
    • 獲取方法
      • Set<Map.Entry<K,V>> entrySet() : 獲取所有的鍵值對(duì)
      • V get(Object key) : 根據(jù)鍵獲取值
      • Set<K> keySet() : 獲取集合中所有鍵的集合
      • Collection<V> values() : 獲取集合中所有值的集合
      • int size() : 返回集合中鍵值對(duì)的個(gè)數(shù)
  4. 演示

    public static void main(String[] args) {
     Map<String, Integer> map = new HashMap<>();
     
     //添加方法
     map.put("小紅", 18);
     map.put("小明", 24);
     map.put("小輝", 26);
     map.put("小李", 19);
     map.put("小王", 18);
     System.out.println(map);
     
     //判斷鍵是否存在
     boolean flg = map.containsKey("小紅");
     System.out.println(flg);
     //判斷值是否存在
     flg = map.containsValue(18);
     System.out.println(flg);
     //判斷集合是否為空
     flg = map.isEmpty();
     System.out.println(flg);
     //根據(jù)鍵獲取值
     Integer i = map.get("小王");
     System.out.println(i);
     //獲取集合中元素的個(gè)數(shù)
     int size = map.size();
     System.out.println(size);
     //獲取集合中所有的鍵值對(duì)
     Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
     System.out.println(entrySet);
     //獲取集合中所有鍵
     Set<String> keyset = map.keySet();
     System.out.println(keyset);
     //獲取集合中所有的值
     Collection<Integer> valueSet = map.values();
     System.out.println(valueSet);
     
    }
    

二. Map集合的遍歷

  1. 獲取所有鍵的集合的遍歷

    • 通過keySet方法獲取到所有鍵的Set集合
    • 演示
    public static void main(String[] args) {
     Map<String, Integer> map = new HashMap<>();
     
     map.put("小紅", 18);
     map.put("小明", 24);
     map.put("小輝", 26);
     map.put("小李", 19);
     map.put("小王", 18);
     
     Set<String> keyset = map.keySet();
     Iterator<String> it = keyset.iterator();
     while (it.hasNext()) {
         String key = it.next();
         Integer value = map.get(key);
         System.out.println("鍵:"+key+" 值:"+value);
     }
    }
    
  2. 獲取所有的值的遍歷

    • 通過values方法獲取所有值的Collection集合
    • 演示
    public static void main(String[] args) {
     Map<String, Integer> map = new HashMap<>();
     
     map.put("小紅", 18);
     map.put("小明", 24);
     map.put("小輝", 26);
     map.put("小李", 19);
     map.put("小王", 18);
     
     Collection<Integer> values = map.values();
     Iterator<Integer> it = values.iterator();
     while (it.hasNext()) {
         Integer value = it.next();
         System.out.println("值:"+value);
     }
    }
    
  3. 獲取所有鍵值對(duì)的遍歷

    • 通過entrySet集合獲取所有的鍵值對(duì)的Set集合
    • 演示
    public static void main(String[] args) {
     Map<String, Integer> map = new HashMap<>();
     
     map.put("小紅", 18);
     map.put("小明", 24);
     map.put("小輝", 26);
     map.put("小李", 19);
     map.put("小王", 18);
     
     Set<Entry<String, Integer>> entrySet = map.entrySet();
     Iterator<Entry<String, Integer>> it = entrySet.iterator();
     while (it.hasNext()) {
         Map.Entry<String,Integer> entry = it.next();
         String key = entry.getKey();
         Integer value = entry.getValue();
         System.out.println("鍵:"+key+" 值:"+value);
     }
    }
    

三. HashMap

  1. 定義

    • 底層使用的是數(shù)組
    • HashMap就是通過我們存入的key獲取到一個(gè)hash值, 經(jīng)過計(jì)算之后, 獲取到一個(gè)數(shù)組角標(biāo), 然后將key和value封裝到一個(gè)Entry里面, 然后存入數(shù)組
    • 當(dāng)數(shù)組容量不夠的時(shí)候, 會(huì)自動(dòng)擴(kuò)容一倍
  1. 構(gòu)造方法

    • HashMap()
      • 構(gòu)造一個(gè)具有默認(rèn)初始容量(16) 和默認(rèn)加載因子(0.75)的空HashMap
    • HashMap(int initialCapacity)
      • 構(gòu)造一個(gè)帶指定初始容量和默認(rèn)加載因子 (0.75) 的空HashMap
    • HashMap(int initialCapacity, float loadFactor)
      • 構(gòu)造一個(gè)帶指定初始容量和加載因子的空HashMap
    • HashMap(Map<? extends K, ?extends V> m)
      • 構(gòu)造一個(gè)映射關(guān)系與制定Map相同的新HashMap
  2. 常用方法

    • put(K key, V value) : 在此映射中關(guān)聯(lián)指定值與指定鍵
    • putAll(Map<? extends K, ?extends V> m) : 將另外一個(gè)map集合復(fù)制到此集合中
  3. 案例

    • HashMap集合鍵是Student值是String的案例
    • 注意
      • 如果我們需要將對(duì)象中的內(nèi)容當(dāng)作比較依據(jù)的話, 就必須要重寫hashCode和equals方法
    • 演示
    public static void main(String[] args) {
     Map<Student, String> map = new HashMap<>();
     
     map.put(new Student("小紅", 18), "美女");
     map.put(new Student("小李", 18), "老板的小舅子");
     
     for (Entry<Student, String> entry : map.entrySet()) {
         System.out.println(entry.getKey()+"::"+entry.getValue());
     }
    }
    
  4. 測(cè)試題

    • 需求: 從鍵盤錄入一串字符, 統(tǒng)計(jì)字符串中每個(gè)字符出現(xiàn)的次數(shù)
    • 演示
    public static void main(String[] args) {
    
     Scanner scanner = new Scanner(System.in);
     
     String str = scanner.nextLine();
     
     HashMap<Character, Integer> hm = new HashMap<>();;
     
     for (int i = 0; i < str.length(); i++) {
         char ch = str.charAt(i);
         if(hm.get(ch)==null)
             hm.put(ch, 1);
         else
             hm.put(ch, hm.get(ch)+1);
     }
     System.out.println(hm);
     scanner.close();
    }
    

四. HashMap和Hashtable的區(qū)別

  1. HashMap和Hashtable的區(qū)別

    • Hashtable是JDK1.0版本出現(xiàn)的,是線程安全的,效率低,HashMap是JDK1.2版本出現(xiàn)的,是線程不安全的,效率高
    • Hashtable不可以存儲(chǔ)null鍵和null值,HashMap可以存儲(chǔ)null鍵和null值
  2. 案例演示

    public static void main(String[] args) {
     Map<String, String> map = new HashMap<>();
    
     map.put("小紅", "美女");
     map.put("小李", "老板的小舅子");
     map.put(null, null);
     
     Hashtable<String, String> table = new Hashtable<>();
     table.put("小紅", "美女");
     //table.put(null, null);//會(huì)報(bào)錯(cuò)
    }
    

五. TreeMap

  1. 定義

    • TreeMap通過比較元素的大小,對(duì)元素進(jìn)行排序, 最后形成了一個(gè)樹狀結(jié)構(gòu)
    • TreeMap中的key需要實(shí)現(xiàn)Comparable接口并重寫compareTo方法, 或者使用Comparator比較器
    • 存入元素的時(shí)候,如果會(huì)將新添加的元素的key和集合中已經(jīng)存在的元素的key比較,返回一個(gè)小于0的數(shù),說明,新添加的元素小于已有元素, 如果返回的是一個(gè)等于0的數(shù),說明新添加的元素等于已有元素, value覆蓋, 如果返回一個(gè)大于0的數(shù),說明新添加的元素大于已有元素
  2. 案例演示

    public static void main(String[] args) {
    
     Map<String, String> map2 = new TreeMap<>();
     map2.put("小紅", "美女");
     map2.put("小紅", "老板的小舅子");
     System.out.println(map2);
    }
    

六. 案例(模擬洗牌和發(fā)牌)

  1. 演示

    public static void main(String[] args) {
     String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
     String[] color = {"方片","梅花","紅桃","黑桃"};
     ArrayList<String> poker = new ArrayList<>();
    
     for(String s1 : color) {
         for(String s2 : num) {
             poker.add(s1.concat(s2));
         }
     }
    
     poker.add("小王");
     poker.add("大王");
     
     Random random = new Random();
     int count = poker.size();
     for (int i = 0; i < count; i++) {
         int index1 = random.nextInt(count);
         int index2 = random.nextInt(count);
         Collections.swap(poker, index1, index2);
     }
     
     List<String> one = new ArrayList<>();
     List<String> two = new ArrayList<>();
     List<String> three = new ArrayList<>();
     List<String> dipai = new ArrayList<>();
     
     /*發(fā)牌*/
     for (int i = 0; i < poker.size(); i++) {
         //最后三張留作底牌
         if(i>=poker.size()-3)
             dipai.add(poker.get(i));
         else if(i%3==0)             //其他三個(gè)人依次發(fā)牌
             one.add(poker.get(i));
         else if(i%3==1)
             two.add(poker.get(i));
         else
             three.add(poker.get(i));
     }
     
     System.out.println(one);
     System.out.println(two);
     System.out.println(three);
     System.out.println(dipai);
    }
    

七. 泛型

  1. 定義

    • 泛型, 即"參數(shù)化類型" , 泛型規(guī)定了類可以使用的應(yīng)用數(shù)據(jù)的類型的范圍
    • 泛型,即“參數(shù)化類型”说莫。一提到參數(shù)姑蓝,最熟悉的就是定義方法時(shí)有形參,然后調(diào)用此方法時(shí)傳遞實(shí)參锅移。那么參數(shù)化類型怎么理解呢熔掺?顧名思義,就是將類型由原來的具體的類型參數(shù)化非剃,類似于方法中的變量參數(shù)瞬女,此時(shí)類型也定義成參數(shù)形式(可以稱之為類型形參),然后在使用/調(diào)用時(shí)傳入具體的類型(類型實(shí)參)
    • 只在編譯期生效
  2. 泛型的好處

    • 提高安全性(將運(yùn)行期的錯(cuò)誤轉(zhuǎn)換到編譯期)
    • 省去強(qiáng)轉(zhuǎn)的麻煩
    • 在其作用域內(nèi)可以統(tǒng)一參數(shù)類型
  3. 泛型的基本使用

    • <>中放的必須是引用數(shù)據(jù)類型
    • 泛型可以定義來類上和方法上
  4. 泛型使用注意事項(xiàng)

    • 前后的泛型必須一致,或者后面的泛型可以省略不寫(1.7的新特性菱形泛型)
  5. 泛型的由來

    • 類型通過Object 轉(zhuǎn)型問題引入
    • 早期的Object類型可以接收任意的對(duì)象類型努潘,但是在實(shí)際的使用中诽偷,會(huì)有類型轉(zhuǎn)換的問題。也就存在這隱患疯坤,所以Java提供了泛型來解決這個(gè)安全問題报慕。
    public class Generic {
     
     private Object object;
    
     public Object getObject() {
         return object;
     }
    
     public void setObject(Object object) {
         this.object = object;
     }
    }
    

八. 泛型的使用

  1. 把泛型定義在類上

    • 格式

      • public class 類名<泛型類型1,…>
    • 注意事項(xiàng)

      • 泛型類型必須是引用類型
    • 演示

      public class Generic<T> {
         
         private T t;
      
         public Object getObject() {
             return t;
         }
      
         public void setObject(T t) {
             this.t = t;
         }
      }
      
  2. 把泛型定義在方法上

    • 格式

      • public <泛型類型> 返回類型 方法名(泛型類型 變量名)
    • 演示

      public <E> E method(E[] e){
         
         return e[e.length/2];
      }
      
  3. 把泛型定義在接口上

    • 格式
      • public interface 接口名<泛型類型>
      • 子類去實(shí)現(xiàn)接口的時(shí)候就需要給出具體的類型, 重寫抽象方法的時(shí)候就可以得到具體的類型
    • 演示
    public interface Inteface<T> {
     
     public void method(T t);
    }
    
  4. 通配符(了解)

    • 泛型通配符<?>

      • 任意類型,如果沒有明確压怠,那么就是Object以及任意的Java類了
      public static void main(String[] args) {
         ArrayList<String> arrayList1 = new ArrayList<>();
         
         ArrayList<Integer> arrayList2 = new ArrayList<>();
         
         List<?> list = arrayList1;
         list = arrayList2;
      }
      
    • ? extends E

      • 向下限定 E 及E的子類
    • ? super E

      • 向上限定 E及其父類

總結(jié)

  1. Map集合

    • 雙列集合 一次性存兩個(gè)值(key-value)
    • key-value : 鍵值對(duì) 映射
    • 特性:
      • key不能重復(fù), value可以重復(fù)
  2. Map集合的方法

    • map集合的方法都是用來操作key的

    • put(key)

    • remove(key) clear

    • get(key)

  3. map集合的遍歷

    • map集合沒有自身的遍歷方法, 要先轉(zhuǎn)成set
    • keySet():獲取所有的key
    • values() : 獲取所有的value
    • entrySet() : 獲取所有的鍵值對(duì)
  4. HashMap

    • 底層是數(shù)組
    • 存儲(chǔ)時(shí),通過key算出一個(gè)角標(biāo)值, 如果當(dāng)前位置上有元素, 就比較一下
      • 如果對(duì)比成功, 覆蓋值
      • 如果沒有成功, 掛載
    • 如果當(dāng)前位置上沒有元素, 直接存儲(chǔ)
    • hashMap是如何判斷是否重復(fù)的 key的地址值和hashCode和equals方法
  5. TreeMap

    • 底層是紅黑樹(二叉樹)
    • key可以排序
    • 新元素要和老元素比較, 根據(jù)返回的結(jié)果判斷存儲(chǔ)的位置
      • 參考TreeSet
  6. HashSet和TreeSet底層用的HashMap和TreeMap

    • 其實(shí)就是將Set集合的元素當(dāng)成Map集合的key
  7. 泛型

    • 設(shè)一個(gè)不是具體類型的類型
    • 好處
      • 提高代碼的兼容性
      • 提高安全性,將運(yùn)行期的錯(cuò)誤提前到編譯期
      • 省去強(qiáng)轉(zhuǎn)的麻煩
      • 在一定范圍統(tǒng)一類型
    • 泛型可以定義的地方
      • 接口, 類, 方法

作業(yè)

  1. 第一題
    • 需求:
      • 封裝一個(gè)汽車類眠冈,包含String name、int speed屬性,在測(cè)試類中實(shí)例化三個(gè)對(duì)象:c1蜗顽,c2布卡,c3,分別設(shè)置name為:“奧拓”雇盖,“寶馬”忿等,“奔馳”,速度分別設(shè)置為:100,200,300
      • 使用Map集合對(duì)象m1將這三個(gè)汽車類對(duì)象保存成key崔挖,然后將int型的汽車價(jià)錢作為值保存在m1的value中贸街,上述三款汽車分別對(duì)應(yīng)的價(jià)錢是10000,500000,2000000
    • 解題
      • 遍歷m1的鍵,打印name屬性
      • 通過合適的方法狸相,求出m1中“寶馬”的價(jià)格薛匪,并打印結(jié)果
      • 經(jīng)過降速,所有汽車都降速到原來的80%脓鹃,請(qǐng)打印降速后“寶馬”的速度
  2. 第二題
    • 需求: 創(chuàng)建倆個(gè)List集合,添加一些數(shù)據(jù)逸尖,求它們的并集,差集和交集瘸右。
  3. 擴(kuò)展題
    1. 第一題
      • 需求: 從鍵盤錄入整數(shù), 打印輸入頻率最高的整數(shù), 如果有多個(gè),就打印多個(gè)
    2. 第二題
      • 需求: 模擬斗地主洗牌發(fā)牌,并對(duì)已發(fā)好的拍進(jìn)行排序(紅桃A,方塊A, 黑桃2.......)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末冷溶,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子尊浓,更是在濱河造成了極大的恐慌逞频,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,590評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件栋齿,死亡現(xiàn)場(chǎng)離奇詭異苗胀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)瓦堵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門基协,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人菇用,你說我怎么就攤上這事澜驮。” “怎么了惋鸥?”我有些...
    開封第一講書人閱讀 169,301評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵杂穷,是天一觀的道長。 經(jīng)常有香客問我卦绣,道長耐量,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,078評(píng)論 1 300
  • 正文 為了忘掉前任滤港,我火速辦了婚禮廊蜒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己山叮,他們只是感情好著榴,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著屁倔,像睡著了一般脑又。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上汰现,一...
    開封第一講書人閱讀 52,682評(píng)論 1 312
  • 那天挂谍,我揣著相機(jī)與錄音叔壤,去河邊找鬼瞎饲。 笑死,一個(gè)胖子當(dāng)著我的面吹牛炼绘,可吹牛的內(nèi)容都是我干的嗅战。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼俺亮,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼驮捍!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起脚曾,我...
    開封第一講書人閱讀 40,098評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤东且,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后本讥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體珊泳,經(jīng)...
    沈念sama閱讀 46,638評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評(píng)論 3 342
  • 正文 我和宋清朗相戀三年拷沸,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了色查。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡撞芍,死狀恐怖秧了,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情序无,我是刑警寧澤验毡,帶...
    沈念sama閱讀 36,520評(píng)論 5 351
  • 正文 年R本政府宣布,位于F島的核電站帝嗡,受9級(jí)特大地震影響米罚,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜丈探,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評(píng)論 3 335
  • 文/蒙蒙 一录择、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦隘竭、人聲如沸塘秦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽尊剔。三九已至,卻和暖如春菱皆,著一層夾襖步出監(jiān)牢的瞬間须误,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評(píng)論 1 274
  • 我被黑心中介騙來泰國打工仇轻, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留京痢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,279評(píng)論 3 379
  • 正文 我出身青樓篷店,卻偏偏與公主長得像祭椰,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子疲陕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容