Java集合框架——Map接口

第三階段 JAVA常見對象的學習

集合框架——Map集合

在實際需求中,咱們經常會遇到這樣的問題,在諸多的數據中,經過其編號來尋找某一些信息,從而進行查看或者修改,例如經過學號查詢學生信息。今天咱們所介紹的Map集合就能夠很好的幫助咱們實現這種需求java

(一) 概述及功能

(1) 概述

Map是一種存儲元素對的集合(元素對分別稱做 鍵 和 值 也稱鍵值對)它將鍵映射到值的對象。一個映射不能包含重複的鍵,而且每一個鍵最 多隻能映射到一個值。面試

怎麼理解呢?數組

鍵 (key):就是你存的值的編號 值 (value):就是你要存放的數據安全

你能夠近似的將鍵理解爲下標,值依據鍵而存儲,每一個鍵都有其對應值。這二者是一、1對應的數據結構

但在以前下標是整數,可是Map中鍵可使任意類型的對象。app

Map集合和Collection集合的區別?框架

  • Map集合存儲元素是成對出現的,Map集合的鍵是惟一的,值是可重複的
  • Collection集合存儲元素是單獨出現的,Collection的子類Set是惟一的,List是可重複的。
  • Map集合的數據結構值針對鍵有效,跟值無關,Collection集合的數據結構是針對元素有效

(2) 功能

A:添加功能工具

//添加元素
put(K key,V value)    //若是鍵是第一次存儲,就直接存儲元素,返回null //若是鍵不是第一次存在,就用值把之前的值替換掉,返回之前的值  複製代碼

B:刪除功能學習

//移除全部的鍵值對元素
void clear() //根據鍵刪除鍵值對元素,並把值返回remove(Object key) 複製代碼

C:判斷功能ui

//判斷集合是否包含指定的鍵
boolean containsKey(Object key) //判斷集合是否包含指定的值 boolean containsValue(Object value) //判斷集合是否爲空 boolean isEmpty() 複製代碼

D:獲取功能

//將map集合中的鍵和值映射關係打包爲一個對象
Set<Map.Entry<K,V>> entrySet()

//根據鍵獲取值
get(Object key) //獲取集合中全部鍵的集合 Set<K> keySet() //獲取集合中全部值的集合 Collection<V> values() 複製代碼

E:長度功能

//返回集合中的鍵值對的對數
int size() 複製代碼

(二) Map集合的遍歷

package cn.bwh_01_iterator;

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

public class MapDemo {
    public static void main(String[] args) {
        Map<String, String> hm = new HashMap<String, String>();
        hm.put("bwh002", "i");
        hm.put("bwh001", "love");
        hm.put("bwh003", "you");

        //方式一 鍵找值
        Set<String> set = hm.keySet();

        //迭代器遍歷
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            String key = it.next();
            String value = hm.get(key);
            System.out.println(key + "---" + value);
        }

        //加強for遍歷
        for (String key : set) {
            String value = hm.get(key);
            System.out.println(key + "---" + value);
        }

        //方式二 鍵值對對象找鍵和值(推薦)
        Set<Map.Entry<String, String>> set2 = hm.entrySet();

        //迭代器遍歷
        Iterator<Map.Entry<String, String>> it2 = set2.iterator();
        while (it2.hasNext()) {
            //返回的是封裝了key和value對象的Map.Entry對象
            Map.Entry<String, String> entry = it2.next();
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "---" + value);

        }

        //加強for遍歷
        for (Map.Entry<String, String> me : set2) {
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key + "---" + value);
        }
    }
}
複製代碼

(三) Map及子類總結

Map(雙列集合)

  • Map集合的數據結構僅僅針對鍵有效,與值無關。

  • 存儲的是鍵值對形式的元素,鍵惟一,值可重複

HashMap

  • 底層數據結構是哈希表,線程不安全,效率高

  • 哈希表依賴兩個方法:hashCod()和equals()

  • 執行順序:

    • 首先判斷hashCode()值是否相同
      • 是:繼續執行equals(),看其返回值
        • 是true:說明元素重複,不添加
        • 是false:就直接添加到集合
      • 否:就直接添加到集合
  • 最終:

  • 自動生成hashCode()和equals()便可

LinkeHashMap

  • 底層數據結構是由鏈表和哈希表組成

  • 由鏈表保證元素有序

  • 由哈希表保證元素惟一

Hashtable

  • 底層數據結構是哈希表
  • 哈希表依賴兩個......自動生成hashCode()和equals()便可

TreeMap

  • 底層數據結構是紅黑樹(是一種自平衡的二叉樹)

如何保證元素惟一性呢?

  • 根據比較的返回值是不是0來決定

如何保證兩種元素的排序呢?

  • 天然排序(元素具有比較性)
    • 讓元素所屬的類實現comparable接口
  • 比較器排序(集合具有比較性)
    • 讓集合接收一個comparator的實現類對象

能夠多層嵌套

HashMap集合嵌套HashMap

HashMap集合嵌套ArrayList

ArrayList集合嵌套HashMap

HashMap<String, ArrayList> hm = new HashMap<String, ArrayList>

1:Hashtable和HashMap的區別?

Hashtable:線程安全,效率低。不容許null鍵和null值

HashMap:線程不安全,效率高。容許null鍵和null值
複製代碼

(其實HashMap就是用來替代Hashtable的,就像ArrayList替代vector同樣)

2:List,Set,Map等接口是否都繼承子Map接口?

List,Set不是繼承自Map接口,它們繼承自Collection接口

Map接口自己就是一個頂層接口

須要排序:TreeMap

不須要排序:HashMap

不知道具體需求:HashMap

(四) 經典案例

(1) 統計字符串中字符出現的次數

import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;

/* * 案例(統計字符串中字符出現的次數) * 需求: * 獲取一個字符串出現的次數 * 分析: * A:定義一個字符串(或者鍵盤錄入) * B: 定義一個TreeMap集合 * 鍵:Character * 值:Integer * C:把字符串轉換爲字符數組 * D: 遍歷字符數組,獲得每個字符 * E: 拿剛纔獲得的字符做爲鍵去集合中找,看返回值 * 是 null:說明該鍵不存在,就把該字符串做爲鍵,1做爲值去存儲 * 不是 null:說明該鍵存在,就把值加 1 而後重寫存儲該鍵和值 * F: 定義字符串緩衝區變量 * G:遍歷集合,獲得該建和值,按照要求拼接 * H:最後把字符串緩衝區轉換爲字符串輸出 */
 
public class CountDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("請輸入須要統計的數據");
        String line = sc.nextLine();

        Map<Character, Integer> tm = new TreeMap<Character, Integer>();
        char[] chs = line.toCharArray();
        for (char ch : chs) {
            Integer i = tm.get(ch);
            if (i == null) {
                tm.put(ch, 1);
            } else {
                i++;
                tm.put(ch, i);
            }
        }

        StringBuilder s = new StringBuilder();
        Set<Character> set = tm.keySet();
        for (Character key : set) {
            Integer value = tm.get(key);
            s.append(key).append("(").append(value).append(")" + " ");
        }
        String result = s.toString();
        System.out.println("result: " + result);
    }
}

//運行結果
請輸入須要統計的數據
HelloWorld
result: H(1) W(1) d(1) e(1) l(3) o(2) r(1) 
複製代碼

(2) 模擬鬥地主案例

在講解這個案例以前,咱們先來了解一個咱們下面案例中所須要知道的知識點

Collections 工具類

Collections:是針對集合進行操做的工具類,都是靜態方法。

面試題:

Collection和Collections的區別?

Collection:是單列集合的頂層接口,有子接口List和Set。(Map是雙列的)

Collections:是針對集合操做的工具類,有對集合進行排序和二分查找的方法

Collections的靜態方法

//排序 默認狀況下是天然順序。
public static <T> void sort(List<T> list) //二分查找 public static <T> int binarySearch(List<?> list,T key) //最大值 public static <T> T max(Collection<?> coll) //反轉(逆序排序) public static void reverse(List<?> list) //隨機置換(猶如洗牌,每次運行結果不同) public static void shuffle(List<?> list) 若是同時有天然排序和比較器排序,以比較器排序爲主(也就是說,當同時實現了Student類的天然排序(implements Comparable<Student>)以及比較器排序的話(new Comparator<Student>()),比較器排序會覆蓋天然排序) 複製代碼
//鬥地主案例代碼
package cn.bwh_03_PokerGame;

import java.util.*;

public class PokerGame {
    public static void main(String[] args) {
        HashMap<Integer, String> hm = new HashMap<Integer, String>();
        ArrayList<Integer> array = new ArrayList<Integer>();

        String[] colors = {"♥", "♠", "♣", "♦"};
        String[] numbers = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};

        int index = 0;
        for (String number : numbers) {
            for (String color : colors) {
                String poker = color.concat(number);
                hm.put(index, poker);
                array.add(index);
                index++;
            }
        }

        hm.put(index, "小王");
        array.add(index);
        index++;
        hm.put(index, "大王");
        array.add(index);
        index++;

        //洗牌
        Collections.shuffle(array);

        //發牌(發的是編號,爲了保證編號是排序的,使用TreeSet接收)
        TreeSet<Integer> player1 = new TreeSet<Integer>();
        TreeSet<Integer> player2 = new TreeSet<Integer>();
        TreeSet<Integer> player3 = new TreeSet<Integer>();
        TreeSet<Integer> handcards = new TreeSet<Integer>();

        for (int x = 0; x < array.size(); x++) {
            if (x >= array.size() - 3) {
                handcards.add(array.get(x));
            } else if (x % 3 == 0) {
                player1.add(array.get(x));
            } else if (x % 3 == 1) {
                player2.add(array.get(x));
            } else if (x % 3 == 2) {
                player3.add(array.get(x));
            }
        }

        System.out.println("---------------------歡樂鬥地主----------------------");
        //看牌(遍歷TreeSet集合,獲取編號,到HashMap集合找對應的牌)
        lookpocker("player1", player1, hm);
        lookpocker("player2", player2, hm);
        lookpocker("player3", player3, hm);
        lookpocker("預留", handcards, hm);
    }

    //看牌功能實現
    public static void lookpocker(String name, TreeSet<Integer> ts, HashMap<Integer, String> hm) {
        System.out.println(name + "的牌是:");
        for (Integer key : ts) {
            String value = hm.get(key);
            System.out.print(value + " ");
        }
        System.out.println();
    }
}
複製代碼

結尾:

若是內容中有什麼不足,或者錯誤的地方,歡迎你們給我留言提出意見, 蟹蟹你們 !^_^

若是能幫到你的話,那就來關注我吧!(系列文章均會在公衆號第一時間更新)

在這裏的咱們素不相識,卻都在爲了本身的夢而努力 ❤

一個堅持推送原創Java技術的公衆號:理想二旬不止

相關文章
相關標籤/搜索