day27_Map接口及常用實現類及Collections工具類

Map接口

概述:現實生活中,我們常會看到這樣的一種集合:IP地址與主機名,身份證號與個人,系統用戶名與系統用戶對象等,這種一一對應的關係,就叫做映射。Java提供了專門的集合類用來存放這種對象關係的對象,即 java.util.Map 接口。我們通過查看 Map 接口描述,發現 Map 接口下的集合與 Collection 接口下的集合,它們存儲數據的形式不同。Collection 中的集合,元素是孤立存在的(理解爲單身),向集合中存儲元素採用一個個元素的方式存儲。Map 中的集合,元素是成對存在的(理解爲夫妻)。每個元素由鍵與值兩部分組成,通過鍵可以找對所對應的值。Collection 中的集合稱爲單列集合, Map 中的集合稱爲雙列集合。需要注意的是, Map 中的集合不能包含重複的鍵,值可以重複;每個鍵只能對應一個值。Map接口中的集合都有兩個泛型變量,在使用時,要爲兩個泛型變量賦予數據類型。兩個泛型變量的數據類型可以相同,也可以不同。

總結一下:Map集合的特點:

  • MapCollection並列存在。用於保存具有映射關係的數據:key-value
  • Map 中的 key value 都可以是任何引用類型的數據
  • Map 中的 key Set來存放,不允許重複,即同一個 Map 對象所對應的類,須重寫hashCode()equals()方法
  • 常用String類作爲Map的“鍵”
  • key value 之間存在單向一對一關係,即通過指定的 key 總能找到 唯一的、確定的 value
  • Map接口的常用實現類:HashMapTreeMapLinkedHashMap和 Properties。其中,HashMapMap 接口使用頻率最高的實現類

Map接口繼承樹

                           

Map接口:常用方法

添加、刪除、修改操作:

  • Object put(Object key,Object value):將指定key-value添加到(或修改)當前map對象中
  • void putAll(Map m):將m中的所有key-value對存放到當前map中
  • Object remove(Object key):移除指定key的key-value對,並返回value
  • void clear():清空當前map中的所有數據

舉例:

 @Test
    public void test1() {
        //創建集合對象
        Map map = new HashMap();
        //添Object put(Object key,Object value):將指定key-value添加到(或修改)當前map對象中
        map.put("AA", 123);
        map.put(45, 123);
        map.put("BB", 56);
        //key重複,會使用新的value替換map中重複的value,返回被替換的value值
        map.put("AA", 87);
        System.out.println(map);//{AA=87, BB=56, 45=123}
 
        Map map1 = new HashMap();
        map1.put("CC", 123);
        map1.put("DD", 123);
        // void putAll(Map m):將m中的所有key-value對存放到當前map中
        map.putAll(map1);
        System.out.println(map);//{AA=87, BB=56, CC=123, DD=123, 45=123}
 
        // Object remove(Object key):移除指定key的key-value對,並返回value
        Object value = map.remove("CC");
        System.out.println(value);//123
        System.out.println(map);//{AA=87, BB=56, DD=123, 45=123}
 
        // void clear():清空當前map中的所有數據
        map.clear();//與map = null操作不同
        System.out.println(map.size());//0
        System.out.println(map);//{}
    }

元素查詢的操作:

  • Object get(Object key):獲取指定key對應的value
  • boolean containsKey(Object key):是否包含指定的key
  • boolean containsValue(Object value):是否包含指定的value
  • int size():返回mapkey-value對的個數
  • boolean isEmpty():判斷當前map是否爲空
  • boolean equals(Object obj):判斷當前map和參數對象obj是否相等

​​​​​​​舉例:

 @Test
    public void test4() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put(45, 123);
        map.put("BB", 56);
        // Object get(Object key):獲取指定key對應的value
        System.out.println(map.get(45));//123
 
        //boolean containsKey(Object key):是否包含指定的key
        boolean isExist = map.containsKey("BB");
        System.out.println(isExist);//true
 
        // boolean containsValue(Object value):是否包含指定的value
        isExist = map.containsValue(123);
        System.out.println(isExist);//true
        map.clear();
 
        //int size():返回map中key-value對的個數
        System.out.println(map.size());//0
        // boolean isEmpty():判斷當前map是否爲空
        System.out.println(map.isEmpty());//true
 
        //boolean equals(Object obj):判斷當前map和參數對象obj是否相等
        Map map1 = new HashMap();
        map1.put("AA", 123);
        map1.put(45, 123);
        map1.put("BB", 56);
        boolean equals = map.equals(map1);
        System.out.println(equals);//false
    }

​​​​​​​元視圖操作的方法:

  • Set keySet():返回所有key構成的Set集合
  • Collection values():返回所有value構成的Collection集合
  • Set entrySet():返回所有key-value對構成的Set集合​​​​​​​

Map實現類之一:HashMap

  • HashMapMap 接口使用頻率最高的實現類。
  • 允許使用null鍵和null值,與HashSet一樣,不保證映射的順序。
  • 所有的key構成的集合是Set:無序的、不可重複的。所以,key所在的類要重寫: equals()和hashCode()
  • 所有的value構成的集合是Collection:無序的、可以重複的。所以,value所在的類 要重寫:equals()
  • 一個key-value構成一個entry
  • 所有的entry構成的集合是Set:無序的、不可重複的
  • HashMap 判斷兩個 key 相等的標準是:兩個 key 通過 equals() 方法返回 true, hashCode 值也相等。
  • HashMap 判斷兩個 value相等的標準是:兩個 value 通過 equals() 方法返回 true​​​​​​​

HashMap的存儲結構

  • JDK 7及以前版本:HashMap是數組+鏈表結構(即爲鏈地址法)
  • JDK 8版本發佈以後:HashMap是數組+鏈表+紅黑樹實現​​​​​​​​​​​​​​

HashMap存儲自定義類型鍵值

  • 當給HashMap中存放自定義對象時,如果自定義對象作爲key存在,這時要保證對象唯一,必須複寫對象的hashCode和equals方法。如果要保證map中存放的key和取出的順序一致,可以使用 java.util.LinkedHashMap 集合來存放。

Map實現類之二:LinkedHashMap

  • LinkedHashMap HashMap 的子類
  • HashMap存儲結構的基礎上,使用了一對雙向鏈表來記錄添加 元素的順序
  • LinkedHashSet類似,LinkedHashMap 可以維護 Map 的迭代 順序:迭代順序與 Key-Value 對的插入順序一致​​​​​​​

Map實現類之三:TreeMap

  • TreeMap存儲 Key-Value 對時,需要根據 key-value 對進行排序。 TreeMap 可以保證所有的 Key-Value 對處於有序狀態。
  • TreeSet底層使用紅黑樹結構存儲數據
  • TreeMap 的 Key 的排序:
  • 自然排序:TreeMap 的所有的 Key 必須實現 Comparable 接口,而且所有 的 Key 應該是同一個類的對象,否則將會拋出 ClasssCastException
  • 定製排序:創建 TreeMap 時,傳入一個 Comparator 對象,該對象負責對
  • TreeMap 中的所有 key 進行排序。此時不需要 Map 的 Key 實現 Comparable 接口
  • TreeMap判斷兩個key相等的標準:兩個key通過compareTo()方法或 者compare()方法返回0。
 
import org.junit.Test;
 
import java.util.*;
 
 
public class TreeMapTest {
 
    //向TreeMap中添加key-value,要求key必須是由同一個類創建的對象
    //因爲要按照key進行排序:自然排序 、定製排序
    //自然排序
    @Test
    public void test1(){
        TreeMap map = new TreeMap();
        User u1 = new User("Tom",23);
        User u2 = new User("Jerry",32);
        User u3 = new User("Jack",20);
        User u4 = new User("Rose",18);
 
        map.put(u1,98);
        map.put(u2,89);
        map.put(u3,76);
        map.put(u4,100);
 
        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while (iterator1.hasNext()){
            Object obj = iterator1.next();
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "---->" + entry.getValue());
 
        }
    }
 
    //定製排序
    @Test
    public void test2(){
        TreeMap map = new TreeMap(new Comparator() {
            @Override
            public int compare(Object o1, Object o2) {
                if(o1 instanceof User && o2 instanceof User){
                    User u1 = (User)o1;
                    User u2 = (User)o2;
                    return Integer.compare(u1.getAge(),u2.getAge());
                }
                throw new RuntimeException("輸入的類型不匹配!");
            }
        });
        User u1 = new User("Tom",23);
        User u2 = new User("Jerry",32);
        User u3 = new User("Jack",20);
        User u4 = new User("Rose",18);
 
        map.put(u1,98);
        map.put(u2,89);
        map.put(u3,76);
        map.put(u4,100);
 
        Set entrySet = map.entrySet();
        Iterator iterator1 = entrySet.iterator();
        while (iterator1.hasNext()){
            Object obj = iterator1.next();
            Map.Entry entry = (Map.Entry) obj;
            System.out.println(entry.getKey() + "---->" + entry.getValue());
 
        }
    }
 
 
}

Map實現類之四:Hashtable

  • Hashtable是個古老的 Map 實現類,JDK1.0就提供了。不同於HashMap, Hashtable是線程安全的。
  • Hashtable實現原理和HashMap相同,功能相同。底層都使用哈希表結構,查詢 速度快,很多情況下可以互用。
  • 與HashMap不同,Hashtable 不允許使用 null 作爲 key value
  • HashMap一樣,Hashtable 也不能保證其中 Key-Value 對的順序
  • Hashtable判斷兩個key相等、兩個value相等的標準,與HashMap一致。

Map實現類之五:Properties

  • Properties 類是 Hashtable 的子類,該對象用於處理屬性文件
  • 由於屬性文件裏的 keyvalue 都是字符串類型,所以 Properties 裏的 key 和 value 都是字符串類型
  • 存取數據時,建議使用setProperty(String key,String value)方法和 getProperty(String key)方法
 
 
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Properties;
 
 
public class PropertiesTest {
 
    //Properties:常用來處理配置文件。key和value都是String類型
    public static void main(String[] args)  {
        FileInputStream fis = null;
        try {
            Properties pros = new Properties();
 
            fis = new FileInputStream("jdbc.properties");
            pros.load(fis);//加載流對應的文件
 
            String name = pros.getProperty("name");
            String password = pros.getProperty("password");
 
            System.out.println("name = " + name + ", password = " + password);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if(fis != null){
                try {
                    fis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
 
            }
        }
 
    }
}

Ma集合遍歷的方式

Map集合遍歷鍵找值方式:即通過元素中的鍵,獲取鍵所對應的值

分析步驟:

  1. 獲取Map中所有的鍵,由於鍵是唯一的,所以返回一個Set集合存儲所有的鍵。方法提示: public Set<K> keySet() : 獲取Map集合中所有的鍵,存儲到Set集合中。
  2. 遍歷鍵的Set集合,得到每一個鍵。
  3. 根據鍵,獲取鍵所對應的值。方法提示: get(K key)

代碼演示:

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
 
/*
    Map集合的第一種遍歷方式:通過鍵找值的方式
    Map集合中的方法:
         Set<K> keySet() 返回此映射中包含的鍵的 Set 視圖。
    實現步驟:
        1.使用Map集合中的方法keySet(),把Map集合所有的key取出來,存儲到一個Set集合中
        2.遍歷set集合,獲取Map集合中的每一個key
        3.通過Map集合中的方法get(key),通過key找到value
 */
public class Demo02KeySet {
    public static void main(String[] args) {
        //創建Map集合對象
        Map<String, Integer> map = new HashMap<>();
        map.put("趙麗穎", 168);
        map.put("楊穎", 165);
        map.put("林志玲", 178);
 
        //1.使用Map集合中的方法keySet(),把Map集合所有的key取出來,存儲到一個Set集合中
        Set<String> set = map.keySet();
 
        //2.遍歷set集合,獲取Map集合中的每一個key
        //使用迭代器遍歷Set集合
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            String key = it.next();
            //3.通過Map集合中的方法get(key),通過key找到value
            Integer value = map.get(key);
            System.out.println(key + "=" + value);
        }
        System.out.println("-------------------");
        //使用增強for遍歷Set集合
        for (String key : set) {
            //3.通過Map集合中的方法get(key),通過key找到value
            Integer value = map.get(key);
            System.out.println(key + "=" + value);
        }
        System.out.println("-------------------");
        //使用增強for遍歷Set集合
        for (String key : map.keySet()) {
            //3.通過Map集合中的方法get(key),通過key找到value
            Integer value = map.get(key);
            System.out.println(key + "=" + value);
        }
    }
}

Entry鍵值對對象

  • 我們已經知道, Map 中存放的是兩種對象,一種稱爲key(鍵),一種稱爲value(值),它們在在 Map 中是一一對應關係,這一對對象又稱做 Map 中的一個 Entry(項) 。 Entry 將鍵值對的對應關係封裝成了對象。即鍵值對對象,這樣我們在遍歷 Map 集合時,就可以從每一個鍵值對( Entry )對象中獲取對應的鍵與對應的值。既然Entry表示了一對鍵和值,那麼也同樣提供了獲取對應鍵和對應值得方法:
  • public K getKey() :獲取Entry對象中的鍵。
  • public V getValue() :獲取Entry對象中的值。

在Map集合中也提供了獲取所有Entry對象的方法:

  • public Set<Map.Entry<K,V>> entrySet() : 獲取到Map集合中所有的鍵值對對象的集合(Set集合)。

鍵值對方式:即通過集合中每個鍵值對(Entry)對象,獲取鍵值對(Entry)對象中的鍵與值

操作步驟:

  1. 獲取Map集合中,所有的鍵值對(Entry)對象,以Set集合形式返回。方法提示: entrySet() 。
  2. 遍歷包含鍵值對(Entry)對象的Set集合,得到每一個鍵值對(Entry)對象。
  3. 通過鍵值對(Entry)對象,獲取Entry對象中的鍵與值。 方法提示: getkey() getValue()

代碼舉例

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
 
/*
    Map集合遍歷的第二種方式:使用Entry對象遍歷
    Map集合中的方法:
        Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射關係的 Set 視圖。
    實現步驟:
        1.使用Map集合中的方法entrySet(),把Map集合中多個Entry對象取出來,存儲到一個Set集合中
        2.遍歷Set集合,獲取每一個Entry對象
        3.使用Entry對象中的方法getKey()和getValue()獲取鍵與值
 */
public class Demo03EntrySet {
    public static void main(String[] args) {
        //創建Map集合對象
        Map<String,Integer> map = new HashMap<>();
        map.put("趙麗穎",168);
        map.put("楊穎",165);
        map.put("林志玲",178);
 
        //1.使用Map集合中的方法entrySet(),把Map集合中多個Entry對象取出來,存儲到一個Set集合中
        Set<Map.Entry<String, Integer>> set = map.entrySet();
 
        //2.遍歷Set集合,獲取每一個Entry對象
        //使用迭代器遍歷Set集合
        Iterator<Map.Entry<String, Integer>> it = set.iterator();
        while(it.hasNext()){
            Map.Entry<String, Integer> entry = it.next();
            //3.使用Entry對象中的方法getKey()和getValue()獲取鍵與值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
        System.out.println("-----------------------");
        for(Map.Entry<String,Integer> entry:set){
            //3.使用Entry對象中的方法getKey()和getValue()獲取鍵與值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
    }
}

Collections工具類

  • Collections 是一個操作 Set、List 和 Map 等集合的工具類 。Collections 中提供了一系列靜態的方法對集合元素進行排序、查詢和修改等操作, 還提供了對集合對象設置不可變、對集合對象實現同步控制等方法。

排序操作(均爲static方法)

  • reverse(List):反轉 List 中元素的順序
  • shuffle(List):對 List 集合元素進行隨機排序
  • sort(List):根據元素的自然順序對指定 List 集合元素按升序排序
  • sort(List,Comparator):根據指定的 Comparator 產生的順序對 List 集合元素進行排序
  • swap(List,int, int):將指定 list 集合中的 i 處元素和 j 處元素進行交換

查找、替換

  • Object max(Collection):根據元素的自然順序,返回給定集合中的最大元素
  • Object max(Collection,Comparator):根據 Comparator 指定的順序,返回 給定集合中的最大元素
  • Object min(Collection)
  • Object min(Collection,Comparator)
  • int frequency(Collection,Object):返回指定集合中指定元素的出現次數
  • void copy(List dest,List src):將src中的內容複製到dest中
  • boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替換 List 對象的所有舊值

Collections 類中提供了多個 synchronizedXxx() 方法,該方法可使將指定集 合包裝成線程同步的集合,從而可以解決多線程併發訪問集合時的線程安全 問題

package com.atguigu.java;
 
import org.junit.Test;
 
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
 
/**
 * Collections:操作Collection、Map的工具類
 *
 */
public class CollectionsTest {
 
/*
reverse(List):反轉 List 中元素的順序
shuffle(List):對 List 集合元素進行隨機排序
sort(List):根據元素的自然順序對指定 List 集合元素按升序排序
sort(List,Comparator):根據指定的 Comparator 產生的順序對 List 集合元素進行排序
swap(List,int, int):將指定 list 集合中的 i 處元素和 j 處元素進行交換
Object max(Collection):根據元素的自然順序,返回給定集合中的最大元素
Object max(Collection,Comparator):根據 Comparator 指定的順序,返回給定集合中的最大元素
Object min(Collection)
Object min(Collection,Comparator)
int frequency(Collection,Object):返回指定集合中指定元素的出現次數
void copy(List dest,List src):將src中的內容複製到dest中
boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替換 List 對象的所有舊值
 */
    @Test
    public void test2(){
        List list = new ArrayList();
        list.add(123);
        list.add(43);
        list.add(765);
        list.add(-97);
        list.add(0);
 
        //報異常:IndexOutOfBoundsException("Source does not fit in dest")
        //  List dest = new ArrayList();
        //  Collections.copy(dest,list);
        //正確的:
        List dest = Arrays.asList(new Object[list.size()]);
        System.out.println(dest.size());//list.size();
        Collections.copy(dest,list);
 
        System.out.println(dest);
 
 
        /*
        Collections 類中提供了多個 synchronizedXxx() 方法,
        該方法可使將指定集合包裝成線程同步的集合,從而可以解決
        多線程併發訪問集合時的線程安全問題
         */
        //返回的list1即爲線程安全的List
        List list1 = Collections.synchronizedList(list);
 
 
    }
 
    @Test
    public void test1(){
        List list = new ArrayList();
        list.add(123);
        list.add(43);
        list.add(765);
        list.add(765);
        list.add(765);
        list.add(-97);
        list.add(0);
 
        System.out.println(list);
 
    // Collections.reverse(list);
    // Collections.shuffle(list);
    // Collections.sort(list);
    // Collections.swap(list,1,2);
        int frequency = Collections.frequency(list, 123);
 
        System.out.println(list);
        System.out.println(frequency);
 
    }
 
}

計算一個字符串中每個字符出現次數 

import java.util.HashMap;
import java.util.Scanner;
 
/*
    分析:
        1.使用Scanner獲取用戶輸入的字符串
        2.創建Map集合,key是字符串中的字符,value是字符的個數
        3.遍歷字符串,獲取每一個字符
        4.使用獲取到的字符,去Map集合判斷key是否存在
            key存在:
                通過字符(key),獲取value(字符個數)
                value++
                put(key,value)把新的value存儲到Map集合中
            key不存在:
                put(key,1)
        5.遍歷Map集合,輸出結果
 */
public class Demo03MapTest {
    public static void main(String[] args) {
        //1.使用Scanner獲取用戶輸入的字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入一個字符串:");
        String str = sc.next();
        //2.創建Map集合,key是字符串中的字符,value是字符的個數
        HashMap<Character, Integer> map = new HashMap<>();
        //3.遍歷字符串,獲取每一個字符
        for (char c : str.toCharArray()) {
            //4.使用獲取到的字符,去Map集合判斷key是否存在
            if (map.containsKey(c)) {
                //key存在
                Integer value = map.get(c);
                value++;
                map.put(c, value);
            } else {
                //key不存在
                map.put(c, 1);
            }
        }
        //5.遍歷Map集合,輸出結果
        for (Character key : map.keySet()) {
            Integer value = map.get(key);
            System.out.println(key + "=" + value);
        }
    }
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章