Java基礎之集合框架系列(四)


1.Map概述

1.概述

1.Map也是集合框架中的一員,獨立於Collection體系。實際上,Collection稱爲單列集合,Map稱爲雙列集合

2.Map集合以鍵值對的方式進行存儲,並且需要保持鍵的唯一性

3.Map包含HashtableHashMapTreeMap三個常見的部分

2.Map接口共性方法

頂級接口 Map<K,V>

頂級接口方法:

1.添加
V put(K key, V value)
向Map集合中添加指定的鍵值對。
說明:若加入兩個鍵名相同的鍵值對,則保存後添加的值,先添加的值會被返回

void putAll(Map<? extends K,? extends V> m)
從指定Map中將所有對應關係複製到此Map中。

2.刪除
>void clear()
從此映射中移除所有映射關係。
V remove(Object key)
如果存在一個鍵的映射關係,則將其從此映射中移除。

3.判斷
boolean containsKey(Object key)
如果此映射包含指定鍵的映射關係,則返回 true。
boolean containsValue(Object value)
如果此映射將一個或多個鍵映射到指定值,則返回 true。
boolean isEmpty()
如果此映射未包含鍵-值映射關係,則返回 true。
boolean equals(Object o)
比較指定的對象與此映射是否相等。

4.獲取
V get(Object key)
返回指定鍵所映射的值;如果此映射不包含該鍵的映射關係,則返回 null。
int size()
返回此映射中的鍵-值映射關係數。
Collection<V> values()
返回此映射中包含的值的 Collection 視圖。
int hashCode()
返回此映射的哈希碼值。
>Set<Map.Entry<K,V>> entrySet()
返回此映射中包含的映射關係的 Set 視圖。
>Set<K> keySet()
返回此映射中包含的鍵的 Set 視圖。

小提示:所謂視圖可以認爲是相應集合類的一個實例對象

示例代碼:

    //以HashMap爲例演示Map的共性方法
    import java.util.HashMap;

    public class MapCommonDemo {

    public static void main(String[] args) {
        //新建HashMap對象,以存儲字符串鍵值對爲例
        HashMap<String,String> hm=new HashMap<String,String>();
        //初始化添加字符串鍵值對元素
        hm.put("key1", "示例元素1");
        hm.put("key2", "示例元素2");
        hm.put("key3", "示例元素3");
        hm.put("key4", "示例元素4");

        //對Map集合進行一次輸出
        System.out.println("原始集合:"+hm);

        //根據鍵獲取字符串值
        System.out.println("根據鍵---key3獲取的元素爲:"+hm.get("key3"));

        //獲取集合的元素數
        System.out.println("該集合所含元素數:"+hm.size());

        //判斷集合是否含有指定的鍵
        System.out.println("判斷集合是否存在特定的鍵---key4:"+hm.containsKey("key4"));      

        //判斷集合是否含有指定的值
        System.out.println("判斷集合是否存在特定的值---示例元素5:"+hm.containsValue("示例元素5"));  

        //通過指定的鍵移除映射關係
        hm.remove("key3");
        System.out.println("進行移除操作後的集合:"+hm);

        //對集合中的元素進行清空
        hm.clear();
        System.out.println("判斷集合是否爲空:"+hm.isEmpty());
    }

}

程序運行結果:

原始集合:{key1=示例元素1, key2=示例元素2, key3=示例元素3, key4=示例元素4}
根據鍵—key3獲取的元素爲:示例元素3
該集合所含元素數:4
判斷集合是否存在特定的鍵—key4:true
判斷集合是否存在特定的值—示例元素5:false
進行移除操作後的集合:{key1=示例元素1, key2=示例元素2, key4=示例元素4}
判斷集合是否爲空:true

3.Map子類對象特點

Hashtable:
底層是哈希表數據結構,不可以存入null鍵和null值。用作鍵的對象必須實現hashCode()方法和equals()方法。該集合是線程同步的。jdk1.0便存在,效率較低。

HashMap:
底層是哈希表數據結構,允許使用null鍵和null值。該集合是非線程同步的。jdk1.2後出現,效率較高

TreeMap:
底層是二叉樹數據結構。該集合是非線程同步的,可以用於對Map集合中的鍵進行排序。

說明:Map的結構與Set相似,實際上Set底層使用了Map集合

4.Map集合的元素取出方式

1.Map-keySet

這是Map集合元素的第一種取出方式

相關方法:

Set<K> keySet()
返回此映射中包含的鍵的 Set 視圖。

說明:通過keySet()將Map中的所有鍵存入到Set集合中,因爲Set具備迭代器,所以能以迭代方式取出所有的鍵。然後再根據Map的get()方法,獲取每一個鍵對應的值。

示例代碼:

        //部分代碼  
        //新建HashMap對象,以存儲字符串鍵值對爲例
        HashMap<String,String> hm=new HashMap<String,String>();
        //初始化添加字符串鍵值對元素
        hm.put("key1", "示例元素1");
        hm.put("key2", "示例元素2");
        hm.put("key3", "示例元素3");
        hm.put("key4", "示例元素4");

        //利用keySet對Map集合中的元素進行輸出
        Set<String> keys = hm.keySet();
        Iterator<String> it = keys.iterator();
        while (it.hasNext()) {
            String key = it.next();          
            System.out.println(key +"--"+hm.get(key));
        }

說明:這也是Map集合和Set集合的聯合使用方式

程序運行結果:

key1–示例元素1
key2–示例元素2
key3–示例元素3
key4–示例元素4

2.Map-entrySet

這是Map集合元素的第二種取出方式

相關方法:

Set<Map.Entry<K,V>> entrySet()
返回此映射中包含的映射關係的 Set 視圖。

說明:將Map集合中的映射關係存入到了Set集合中,而這個關係的數據類型就是Map.Entry

注意:此時迭代器的泛型也應該與返回的Set集合泛型一致,即<Map.Entry<K,V>>

接口 Map.Entry<K,V>

相關方法:

boolean equals(Object o)
比較指定對象與此項的相等性。
K getKey()
返回與此項對應的鍵。
V getValue()
返回與此項對應的值。
int hashCode()
返回此映射項的哈希碼值。
V setValue(V value)
用指定的值替換與此項對應的值。

說明:實際上Map.Entry是Map接口中的一個內部接口

示例代碼:

        //部分代碼
        //新建HashMap對象,以存儲字符串鍵值對爲例
        HashMap<String,String> hm=new HashMap<String,String>();
        //初始化添加字符串鍵值對元素
        hm.put("key1", "示例元素1");
        hm.put("key2", "示例元素2");
        hm.put("key3", "示例元素3");
        hm.put("key4", "示例元素4");

        //利用entrySet對Map集合中的元素進行輸出
        Set<Map.Entry<String,String>> entry=hm.entrySet();
        Iterator<Map.Entry<String,String>> it=entry.iterator();
        while(it.hasNext()){
            Map.Entry<String,String> me=it.next();
            System.out.println(me.getKey()+"---"+me.getValue());
        }

程序運行結果:

key1—示例元素1
key2—示例元素2
key3—示例元素3
key4—示例元素4

5.HashMap

HashMap()
構造一個具有默認初始容量 (16) 和默認加載因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity)
構造一個帶指定初始容量和默認加載因子 (0.75) 的空 HashMap。
HashMap(int initialCapacity, float loadFactor)
構造一個帶指定初始容量和加載因子的空 HashMap。
HashMap(Map<? extends K,? extends V> m)
構造一個映射關係與指定 Map 相同的新 HashMap。

特有方法:

Object clone()
返回此 HashMap 實例的淺表副本,並不複製鍵和值本身。
Set<Map.Entry<K,V>> entrySet()
返回此映射所包含的映射關係的 Set 視圖。
Set<K> keySet()
返回此映射中所包含的鍵的 Set 視圖。

6.TreeMap

構造方法:

TreeMap()
使用鍵的自然順序構造一個新的、空的樹映射。
TreeMap(Comparator<? super K> comparator)
構造一個新的、空的樹映射,該映射根據給定比較器進行排序。
TreeMap(Map<? extends K,? extends V> m)
構造一個與給定映射具有相同映射關係的新的樹映射,該映射根據其鍵的自然順序 進行排序。
TreeMap(SortedMap<K,? extends V> m)
構造一個與指定有序映射具有相同映射關係和相同排序順序的新的樹映射。

特有方法:

Object clone()
返回此 TreeMap 實例的淺表副本。

Comparator<? super K> comparator()
返回對此映射中的鍵進行排序的比較器;如果此映射使用鍵的自然順序,則返回 null。


Map.Entry<K,V> firstEntry()
返回一個與此映射中的最小鍵關聯的鍵-值映射關係;如果映射爲空,則返回 null。
K firstKey()
返回此映射中當前第一個(最低)鍵。
K lastKey()
返回映射中當前最後一個(最高)鍵。
Map.Entry<K,V> lastEntry()
返回與此映射中的最大鍵關聯的鍵-值映射關係;如果映射爲空,則返回 null。

Map.Entry<K,V> pollFirstEntry()
移除並返回與此映射中的最小鍵關聯的鍵-值映射關係;如果映射爲空,則返回 null。
Map.Entry<K,V> pollLastEntry()
移除並返回與此映射中的最大鍵關聯的鍵-值映射關係;如果映射爲空,則返回 null。


Map.Entry<K,V> ceilingEntry(K key)
返回一個鍵-值映射關係,它與大於等於給定鍵的最小鍵關聯;如果不存在這樣的鍵,則返回 null。
K ceilingKey(K key)
返回大於等於給定鍵的最小鍵;如果不存在這樣的鍵,則返回 null。
Map.Entry<K,V> floorEntry(K key)
返回一個鍵-值映射關係,它與小於等於給定鍵的最大鍵關聯;如果不存在這樣的鍵,則返回 null。
K floorKey(K key)
返回小於等於給定鍵的最大鍵;如果不存在這樣的鍵,則返回 null。

Map.Entry<K,V> higherEntry(K key)
返回一個鍵-值映射關係,它與嚴格大於給定鍵的最小鍵關聯;如果不存在這樣的鍵,則返回 null。
K higherKey(K key)
返回嚴格大於給定鍵的最小鍵;如果不存在這樣的鍵,則返回 null。
K lowerKey(K key)
返回嚴格小於給定鍵的最大鍵;如果不存在這樣的鍵,則返回 null。
Map.Entry<K,V> lowerEntry(K key)
返回一個鍵-值映射關係,它與嚴格小於給定鍵的最大鍵關聯;如果不存在這樣的鍵,則返回 null。


NavigableSet<K> descendingKeySet()
返回此映射中所包含鍵的逆序 NavigableSet 視圖。
NavigableMap<K,V> descendingMap()
返回此映射中所包含映射關係的逆序視圖。

SortedMap<K,V> headMap(K toKey)
返回此映射的部分視圖,其鍵值嚴格小於 toKey。
NavigableMap<K,V> headMap(K toKey, boolean inclusive)
返回此映射的部分視圖,其鍵小於(或等於,如果 inclusive 爲 true)toKey。

NavigableSet<K> navigableKeySet()
返回此映射中所包含鍵的 NavigableSet 視圖。

NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)
返回此映射的部分視圖,其鍵的範圍從 fromKey 到 toKey。
SortedMap<K,V> subMap(K fromKey, K toKey)
返回此映射的部分視圖,其鍵值的範圍從 fromKey(包括)到 toKey(不包括)。

SortedMap<K,V> tailMap(K fromKey)
返回此映射的部分視圖,其鍵大於等於 fromKey。
NavigableMap<K,V> tailMap(K fromKey, boolean inclusive)
返回此映射的部分視圖,其鍵大於(或等於,如果 inclusive 爲 true)fromKey。

7.相關實例應用

1.Map應用

需求描述:

自定義Worker對象,具有年齡和姓名屬性,姓名和年齡相同的對象視爲同一個Worker對象,以保證元素唯一性。將Worker對象作爲鍵,其家庭住址作爲值,存入Map集合

步驟:

1.描述Worker對象,複寫hashCode()equals()方法,實現Comparable接口,實現compareTo()方法。
2.定義Map容器,將Worker對象作爲鍵,Worker地址作爲值,進行存入。
3.對Map中的元素進行獲取操作。

示例代碼:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

class Worker implements Comparable{
    private String name;
    private int age;
    //構造方法
    public Worker(String name,int age){
        this.name=name;
        this.age=age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    //重寫hashCode方法
    public int hashCode() {
        return name.hashCode()+age*39;
    }

    //重寫equals方法
    public boolean equals(Object obj) {
        if(!(obj instanceof Worker))
            return false;
        Worker w=(Worker)obj;
        if(!name.equals(w.getName()))
            return false;
        if(age==w.getAge())
            return true;
        return false;
    }

    //實現compareTo方法
    public int compareTo(Object o){
        if(!(o instanceof Worker))
            throw new RuntimeException("類型錯誤");
        Worker w=(Worker)o;
        int status=name.compareTo(w.getName());
        if(status==0)
            return new Integer(age).compareTo(new Integer(w.getAge()));
        return status;
    }

}

public class WorkerMapDemo {

    public static void main(String[] args) {
        //新建HashMap集合
        HashMap<Worker,String> hm=new HashMap<Worker,String>();
        //向HashMap集合中添加Worker-地址鍵值對
        hm.put(new Worker("小王",25), "北京");
        hm.put(new Worker("小王",25), "天津");
        hm.put(new Worker("小李",20), "廣東");
        hm.put(new Worker("小黃",24), "山西");
        hm.put(new Worker("小曹",22), "山西");

        //利用keySet對HashMap中的元素進行取出
        Set<Worker> sw=hm.keySet();
        Iterator<Worker> it=sw.iterator();
        while(it.hasNext()){
            Worker w=it.next();
            System.out.println(w.getName()+"--"+w.getAge()+"--"+hm.get(w));
        }
    }

}

程序運行結果:

小王–25–天津
小李–20–廣東
小黃–24–山西
小曹–22–山西

說明:從程序中可以看出,當向集合中存入鍵相同的鍵值對時,後存入的鍵值對會覆蓋先存入的鍵值對。

相關思想:如果自定義的類可能實例化多個對象,則應該考慮到該類的對象可能會存入Set,List,Map等多種集合結構中,因此需要考慮重寫hashCode()equals()方法,以及實現Comparable接口,實現其compareTo()方法

2.TreeMap應用

1.排序

需求描述:

構造Worker對象,按照年齡對Worker對象進行升序排序

說明:
1.由於數據是以鍵值對形式存在的,所以需要要使用可以排序的Map子類集合對象TreeMap
2.運用比較器Comparator進行自定義排序,類似於TreeSet的處理方式

示例代碼:

//省略Worker類代碼
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

//自定義比較器類,按照Worker對象的年齡升序排序
class WorkerComparator implements Comparator<Worker>{

    //重寫compare方法
    public int compare(Worker w1, Worker w2) {
        if(w1.getAge()>w2.getAge())
            return 1;
        if(w1.getAge()==w2.getAge())
            //當年齡相同時則將姓名作爲次要排序條件
            return w1.getName().compareTo(w2.getName());
        else
            return -1;
    }

}

public class TreeMapCompDemo {

    public static void main(String[] args) {
        //實例化自定義比較器對象
        WorkerComparator wc=new WorkerComparator();
        //新建TreeMap集合裝載Worker-地址鍵值對
        TreeMap<Worker,String> tm=new TreeMap<Worker,String>(wc);
        //向TreeMap集合中添加Worker-地址鍵值對
        tm.put(new Worker("小王", 25), "北京");
        tm.put(new Worker("小李", 20), "廣東");
        tm.put(new Worker("小黃", 28), "山西");
        tm.put(new Worker("小曹", 19), "山西");

        //使用entrySet取出元素
        Set<Map.Entry<Worker,String>> entry=tm.entrySet();
        Iterator<Map.Entry<Worker,String>> it=entry.iterator();
        while(it.hasNext()){
            Map.Entry<Worker,String> me=it.next();
            Worker w=me.getKey();
            System.out.println(w.getName()+"--"+w.getAge()+"--"+me.getValue());
        }

    }

}

程序運行結果:

小曹–19–山西
小李–20–廣東
小王–25–北京
小黃–28–山西

2.統計

需求描述:

統計字符串中各個字母出現的次數,並按照字母的在字母表中的排列順序分別對出現次數進行輸出

思路:通過需要的結果發現:每一個字母都有對應的次數,說明字母和次數之間都有映射關係,因此可以選擇Map集合

步驟:
1.將字符串轉換爲字符數組,因爲要對每一個字母進行操作

2.定義一個Map集合,因爲打印結果的字母有順序,所以用TreeMap集合

3.遍歷字符數組,將遍歷到的每一個字母作爲鍵查找Map集合中的元素。若返回null,說明Map集合中該字母還不存在,將該字母和1作爲鍵值對存入Map集合中。若返回值不爲null,那麼獲取該鍵的值並自增後存入

4.將Map集合中的數據按照要求的格式進行輸出

示例代碼:


import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

public class StringCountCharDemo {

    //自定義靜態方法方法統計字符串中出現的字母次數
    public static void countChar(String s,HashMap<Character,Integer> hm){
        //將字符串轉化爲字符數組
        char[] c=s.toCharArray();
        //遍歷字符數組,並進行計數
        for(int i=0;i<c.length;i++){
            if(!hm.containsKey(c[i]))
                hm.put(c[i], 1);
            else{
                int count=hm.get(c[i]);             
                hm.put(c[i],++count);
            }
        }
    }

    public static void main(String[] args) {
        //目標字符串
        String target="aasdadasfefftyytudada";
        //新建HashMap對象存儲字母-頻次鍵值對
        HashMap<Character,Integer> hm=new HashMap<Character,Integer>();

        //統計字母頻次
        countChar(target,hm);

        //對HashMap集合中的元素進行取出
        Set<Character> ks=hm.keySet();
        Iterator<Character> it=ks.iterator();
        while(it.hasNext()){
            Character key=it.next();
            System.out.print(key+"("+hm.get(key)+")");
        }
    }

}

程序運行結果:

a(6)s(2)d(4)t(2)e(1)u(1)f(3)y(2)

3.Map拓展

集合的嵌套使用:在Map集合中,還可以將Map集合對象作爲值,實現Map的嵌套使用

示例代碼:

        //部分代碼
        //新建HashMap對象儲存高中學生信息
        HashMap<String,Integer> highSchStu=new HashMap<String,Integer>();
        highSchStu.put("bill",16);
        highSchStu.put("tony",15);
        highSchStu.put("marry",18);

        //新建HashMap對象儲存大學學生信息
        HashMap<String,Integer> colSchStu=new HashMap<String,Integer>();
        colSchStu.put("tim",20);
        colSchStu.put("park",22);
        colSchStu.put("curry",19);

        //新建HashMap對象儲存已經建立的兩個HashMap對象
        HashMap<String,HashMap<String,Integer>> schoolStu=
                new HashMap<String,HashMap<String,Integer>>();
        schoolStu.put("高中學生信息:",highSchStu);
        schoolStu.put("大學學生信息:",colSchStu);

        //利用keySet對元素進行取出
        Set<String> keys=schoolStu.keySet();
        Iterator<String> it=keys.iterator();    
        while(it.hasNext()){
            String key=it.next();
            HashMap<String,Integer> hm=schoolStu.get(key);
            //直接將獲取到的整個集合輸出
            System.out.println(key+hm);
        }

程序運行結果:

高中學生信息:{tony=15, marry=18, bill=16}
大學學生信息:{tim=20, curry=19, park=22}


相關閱讀:
菜鳥猿大戰Java之集合框架系列(一)
菜鳥猿大戰Java之集合框架系列(二)
菜鳥猿大戰Java之集合框架系列(三)
菜鳥猿大戰Java之集合框架系列(五)

發佈了49 篇原創文章 · 獲贊 77 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章