深入了解Map

聯(lián)系

Java中的Map類似于OC的Dictionary,都是一個(gè)個(gè)鍵值對(duì)組成,一鍵對(duì)應(yīng)一值。我在之前的文章中講解過(guò)Set,其實(shí)在JAVA底層Set依賴的也是Map,那我們都知道,Set是單列的(只有值),而Map是雙列的,怎么會(huì)是Set依賴Map呢?其實(shí)做法也很簡(jiǎn)單,Set將Key隱藏,只允許訪問(wèn)value就實(shí)現(xiàn)了Set的單列效果。

功能

*a:添加功能
    * V put(K key,V value):添加元素。
        * 如果鍵是第一次存儲(chǔ),就直接存儲(chǔ)元素,返回null
        * 如果鍵不是第一次存在,就用值把以前的值替換掉,返回以前的值
Map<String, Interger> map = new HashMap();
map.put("張三",23);

這里需要注意Map中的重復(fù)的鍵不存儲(chǔ),值覆蓋返回

* b:刪除功能
    * void clear():移除所有的鍵值對(duì)元素
    * V remove(Object key):根據(jù)鍵刪除鍵值對(duì)元素,并把值返回
Map<String, Interger> map = new HashMap();
map.put("張三",23);
map.remove("張三");根據(jù)鍵刪除元素
* c:判斷功能
    * boolean containsKey(Object key):判斷集合是否包含指定的鍵
    * boolean containsValue(Object value):判斷集合是否包含指定的值
    * boolean isEmpty():判斷集合是否為空
Map<String, Interger> map = new HashMap();
map.put("張三",23);
System.out.println(map.containsKey("張三"));      //判斷集合是否包含指定的鍵
System.out.println(map.containsValue(100));         //判斷集合是否包含指定的值
* d:獲取功能
    * Set<Map.Entry<K,V>> entrySet():
    * V get(Object key):根據(jù)鍵獲取值
    * Set<K> keySet():獲取集合中所有鍵的集合
    * Collection<V> values():獲取集合中所有值的集合
Map<String, Interger> map = new HashMap();
map.put("張三",23);
Collection<Integer> c = map.values();
* e:長(zhǎng)度功能
    * int size():返回集合中的鍵值對(duì)的個(gè)數(shù)
Map<String, Interger> map = new HashMap();
map.put("張三",23);
System.out.println(map.size());  

size()方法以鍵值對(duì)的個(gè)數(shù)統(tǒng)計(jì),上述map.size()為1而不是2。

Map的遍歷

方式一
  //通過(guò)獲取所有的鍵來(lái)遍歷值
        Map<String, Integer> map = new HashMap<>();
        map.put("張三", 23);
        map.put("李四", 24);
        map.put("王五", 25);
        map.put("趙六", 26);

        Set<String> keySet = map.keySet();          //獲取所有鍵的集合
        Iterator<String> it = keySet.iterator();    //獲取迭代器
        while(it.hasNext()) {                       //判斷集合中是否有元素
            String key = it.next();                 //獲取每一個(gè)鍵
            Integer value = map.get(key);           //根據(jù)鍵獲取值
            System.out.println(key + "=" + value);
        }

使用迭代器遍歷,但是有些復(fù)雜,可以改進(jìn)

方式二 (方式一改進(jìn),較簡(jiǎn)單)

這種遍歷方式類似于OC中for···in語(yǔ)法

        //使用增強(qiáng)for循環(huán)遍歷
        for(String key : map.keySet()) {            //map.keySet()是所有鍵的集合
            System.out.println(key + "=" + map.get(key));
        }
方式三 鍵值對(duì)對(duì)象遍歷
        //Map.Entry說(shuō)明Entry是Map的內(nèi)部接口,將鍵和值封裝成了Entry對(duì)象,并存儲(chǔ)在Set集合中
        Set<Map.Entry<String, Integer>> entrySet = map.entrySet();
        //獲取每一個(gè)對(duì)象
        Iterator<Map.Entry<String, Integer>> it = entrySet.iterator();
        while(it.hasNext()) {
            //獲取每一個(gè)Entry對(duì)象
            Map.Entry<String, Integer> en = it.next();  //父類引用指向子類對(duì)象
            //Entry<String, Integer> en = it.next();    //直接獲取的是子類對(duì)象
            String key = en.getKey();                   //根據(jù)鍵值對(duì)對(duì)象獲取鍵
            Integer value = en.getValue();              //根據(jù)鍵值對(duì)對(duì)象獲取值
            System.out.println(key + "=" + value);
        }
方式四 (方式三改進(jìn))
        for(Entry<String, Integer> en : map.entrySet()) {
            System.out.println(en.getKey() + "=" + en.getValue());
        }

LinkedHashMap

LinkedHashMap可以保證怎么存就怎么取

    public static void main(String[] args) {
        LinkedHashMap<String, Integer> lhm = new LinkedHashMap<>();
        lhm.put("張三", 23);
        lhm.put("李四", 24);
        lhm.put("趙六", 26);
        lhm.put("王五", 25);
        
        System.out.println(lhm);
    }

TreeMap

利用TreeMap可實(shí)現(xiàn)對(duì)鍵的自定義排序,同時(shí)鍵應(yīng)為自定義類對(duì)象,同時(shí)需要在自定義類中重寫compareTo方法,和hashSet里面的排序大致相同。

//按照Student的姓名排序,姓名相同按照年齡排序
public static void main(String[] args) {
        //demo1();
        TreeMap<Student, String> tm = new TreeMap<>(new Comparator<Student>() {

            @Override
            public int compare(Student s1, Student s2) {
                int num = s1.getName().compareTo(s2.getName());     //按照姓名比較
                return num == 0 ? s1.getAge() - s2.getAge() : num;
            }
        });
        tm.put(new Student("張三", 23), "北京");
        tm.put(new Student("李四", 13), "上海");
        tm.put(new Student("趙六", 43), "深圳");
        tm.put(new Student("王五", 33), "廣州");
        
        System.out.println(tm);
    }

利用HashMap統(tǒng)計(jì)字符串中每個(gè)字符出現(xiàn)的次數(shù)

核心思想就是利用HashMap的containsKey()來(lái)判斷是否重復(fù)。

/**
     * * A:案例演示
     * 需求:統(tǒng)計(jì)字符串中每個(gè)字符出現(xiàn)的次數(shù)
     * 
     * 分析:
     * 1,定義一個(gè)需要被統(tǒng)計(jì)字符的字符串
     * 2,將字符串轉(zhuǎn)換為字符數(shù)組
     * 3,定義雙列集合,存儲(chǔ)字符串中字符以及字符出現(xiàn)的次數(shù)
     * 4,遍歷字符數(shù)組獲取每一個(gè)字符,并將字符存儲(chǔ)在雙列集合中
     * 5,存儲(chǔ)過(guò)程中要做判斷,如果集合中不包含這個(gè)鍵,就將該字符當(dāng)作鍵,值為1存儲(chǔ),如果集合中包含這個(gè)鍵,就將值加1存儲(chǔ)
     * 6,打印雙列集合獲取字符出現(xiàn)的次數(shù)
     */
    public static void main(String[] args) {
        //1,定義一個(gè)需要被統(tǒng)計(jì)字符的字符串
        String s = "aaaabbbbbccccccccccccc";
        //2,將字符串轉(zhuǎn)換為字符數(shù)組
        char[] arr = s.toCharArray();
        //3,定義雙列集合,存儲(chǔ)字符串中字符以及字符出現(xiàn)的次數(shù)
        HashMap<Character, Integer> hm = new HashMap<>();
        //4,遍歷字符數(shù)組獲取每一個(gè)字符,并將字符存儲(chǔ)在雙列集合中
        for(char c: arr) {
            //5,存儲(chǔ)過(guò)程中要做判斷,如果集合中不包含這個(gè)鍵,就將該字符當(dāng)作鍵,值為1存儲(chǔ),如果集合中包含這個(gè)鍵,就將值加1存儲(chǔ)
            /*if(!hm.containsKey(c)) {          //如果不包含這個(gè)鍵
                hm.put(c, 1);
            }else {
                hm.put(c, hm.get(c) + 1);
            }*/
            hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
        }
        //6,打印雙列集合獲取字符出現(xiàn)的次數(shù)
        
        for (Character key : hm.keySet()) {             //hm.keySet()代表所有鍵的集合
            System.out.println(key + "=" + hm.get(key));//hm.get(key)根據(jù)鍵獲取值
        }
    }
案例演示:

集合嵌套之HashMap嵌套HashMap

需求:

一個(gè)年級(jí)有很多班,
一班定義為一個(gè)雙列結(jié)合,鍵是學(xué)生對(duì)象,值是學(xué)生的歸屬地,
二班定義為一個(gè)雙列結(jié)合,鍵是學(xué)生對(duì)象,值是學(xué)生的歸屬地。
無(wú)論一班二班都是班級(jí)對(duì)象,所以為了編譯統(tǒng)一管理,把這些班級(jí)對(duì)象添加到某個(gè)年級(jí)中。

        //定義一班
        HashMap<Student, String> hm88 = new HashMap<>();
        hm88.put(new Student("張三", 23), "北京");
        hm88.put(new Student("李四", 24), "北京");
        hm88.put(new Student("王五", 25), "上海");
        hm88.put(new Student("趙六", 26), "廣州");
        
        //定義二班
        HashMap<Student, String> hm99 = new HashMap<>();
        hm99.put(new Student("唐僧", 1023), "北京");
        hm99.put(new Student("孫悟空",1024), "北京");
        hm99.put(new Student("豬八戒",1025), "上海");
        hm99.put(new Student("沙和尚",1026), "廣州");
        
        //定義年級(jí)
        HashMap<HashMap<Student, String>, String> hm = new HashMap<>();
        hm.put(hm88, "一班");
        hm.put(hm99, "二班");
        
        //遍歷雙列集合
        for(HashMap<Student, String> h : hm.keySet()) {     //hm.keySet()代表的是雙列集合中鍵的集合
            String value = hm.get(h);                       //get(h)根據(jù)鍵對(duì)象獲取值對(duì)象
            //遍歷鍵的雙列集合對(duì)象
            for(Student key : h.keySet()) {                 //h.keySet()獲取集合總所有的學(xué)生鍵對(duì)象
                String value2 = h.get(key);
                
                System.out.println(key + "=" + value2 + "=" + value);
            }
        }

hashMap和hashTable的區(qū)別

共同點(diǎn):

底層都是哈希算法,都是雙列集合

區(qū)別:
  1. HashMap是線程不安全的,效率高,JDK1.2版本,Hashtable是線程安全的,效率低,JDK1.0版本的
  2. HashMap可以存儲(chǔ)null鍵和null值,Hashtable不可以存儲(chǔ)null鍵和null值
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類相關(guān)的語(yǔ)法,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚_t_閱讀 34,806評(píng)論 18 399
  • 注意事項(xiàng): 使用 entrySet 遍歷 Map 類集合 KV,而不是 keySet 方式進(jìn)行遍歷。 說(shuō)明:key...
    yuanfy閱讀 1,676評(píng)論 1 9
  • 原文轉(zhuǎn)自:http://www.54tianzhisheng.cn/2017/06/10/HashMap-Hash...
    beneke閱讀 3,226評(píng)論 1 66
  • java筆記第一天 == 和 equals ==比較的比較的是兩個(gè)變量的值是否相等,對(duì)于引用型變量表示的是兩個(gè)變量...
    jmychou閱讀 1,658評(píng)論 0 3
  • 那一天,我?guī)е鴥蓚€(gè)寶貝走在那個(gè)我愛慕已久的小區(qū)里,小區(qū)的花開的正好。 可能是在綠化面積太小的小區(qū)里住的太久了,寶貝...
    余渡閱讀 185評(píng)論 0 4

友情鏈接更多精彩內(nèi)容