32、【JavaSE】【Java 核心类库(上)】集合类-Map

1、概述

  • Map 是 Java 集合体系中的另一个体系,之前的是 Collection。当然并不是说这个两个体系之间没有了交集,这样只是说学习起来比较让人容易接受。

  • Map 体系的最顶层是java.util.Map这个接口,这与前面的java.util.Collection接口是一样的思路。

Map 接口与实现类
  • Map 与前面的 Collection 不同,存入其中的元素是成对的,这个每一对元素用一个专业的术语就是“键值对”,每一对元素,其中一个是“键”(key),另一个是“值”(value),“键”与“值”是一一对应的。Map 就是用来存放多个“键值对”的这样一个集合。形象的说法是,将一个 Map 比喻成一本书,所有的“键”构成了这本书的目录,目录会告诉读者对应的内容在什么地方,也就是通过“键”就能找到“值”。

  • 在 Map 中,最基本的规则是,“键”不允许重复、“键”与“值”必须保证是一对一的关系。

  • java.util.Map同样是支持使用泛型的,而通过上面的解读,可以大概清楚其泛型是怎么指定的,Map<K, V>,键与值的泛型都要分别指定。

  • java.util.Map的主要的实现类有:java.util.HashMapjava.util.LinkedHashMapjava.util.TreeMapjava.util.Hashtablejava.util.Properties等。

  • java.util.HashMap底层所采用的数据结构是哈希表。之前的java.util.HashSet从本质上说是一个 HashMap 。

public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable {

    ······

    private transient HashMap<E,Object> map;

    public HashSet() {
        map = new HashMap<>();
    }

    ······

}
  • java.util.TreeMap底层所采用的数据结构是红黑树。之前的java.util.TreeSet从本质上来说是一个 TreeMap 。和java.util.TreeSet一样,放入其中的元素也是必须具有可比性的。
public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable {

   ······

   public TreeSet() {
        this(new TreeMap<>());
    }

   ······
}
  • java.util.LinkedHashMap类与java.util.HashMap类的不同之处在于内部维护了一个双向链表,通过链表中记录了元素的迭代顺序,也就是元素插入集合中的先后顺序,因此便于迭代。

  • java.util.Hashtable类是一个老的java.util.Map实现类,与java.util.HashMap类相比属于线程安全的类,且不允许null作为 key 或者 value 的数值。

  • java.util.Properties类是java.util.Hashtable类的子类,该对象用于处理属性文件,属性文件中的 key 和 value 都是java.util.String类型的。注意,java.util.Properties类是不需要指定泛型的

Properties properties = new Properties();
  • Map 与 Set 之间有比较密切的关系,Set 的底层是在通过 Map 实现的。Set 中的元素实际上是作为 Map 中的 key 。
Set 集合与 Map 集合

2、Map 接口中的常用方法

Map 接口中常用方法
  • 添加与修改
import java.util.HashMap;
import java.util.Map;

public class MapTest {

    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();

        // 对于 Map 中不存在的“键”,使用 put 方法可以添加
        map.put(1, "张三");
        map.put(2, "李四");
        System.out.println(map); // {1=张三, 2=李四}

        // 对于 Map 中存在的“键”,使用 put 方法是修改
        map.put(1, "王五");
        System.out.println(map); // {1=王五, 2=李四}
    }

}
  • 查找
import java.util.HashMap;
import java.util.Map;

public class MapTest {

    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();

        map.put(1, "张三");
        map.put(2, "李四");
        map.put(3, "王五");

        boolean b1 = map.containsKey(1);
        System.out.println(b1); // true

        boolean b2 = map.containsValue("张思");
        System.out.println(b2); // false

        Object obj1 = map.get(5);
        System.out.println(obj1); // null

        Object obj2 = map.get(3);
        System.out.println(obj2); // 王五
    }

}
  • 删除
import java.util.HashMap;
import java.util.Map;

public class MapTest {

    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();

        map.put(1, "张三");
        map.put(2, "李四");
        map.put(3, "王五");
        System.out.println(map); // {1=张三, 2=李四, 3=王五}

        String s1 = map.remove(5);
        System.out.println(s1); // null

        String s2 = map.remove(1);
        System.out.println(s2); // 张三
        System.out.println(map); // {2=李四, 3=王五}
    }

}
  • Map 的遍历

java.util.Map接口并没有继承java.util.Iterator这个接口,所以,不能使用 for-each 来遍历 Map!

1、使用keySet方法,获取包含有全部“键”的 Set,然后通过get方法进而实现对 Map 的遍历。

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

public class MapTest {

    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();

        map.put(1, "张三");
        map.put(2, "李四");
        map.put(3, "王五");
        System.out.println(map);

        Set<Integer> set = map.keySet();
        for (Integer key : set) {
            System.out.println(key + "=" + map.get(key));
        }
    }

}

{1=张三, 2=李四, 3=王五}
1=张三
2=李四
3=王五

2、使用values方法,获取 Map 中全部的“值”。但是,这种方法对于想获取“值”对应的“键”而言并不友好。

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class MapTest {

    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();

        map.put(1, "张三");
        map.put(2, "李四");
        map.put(3, "王五");
        System.out.println(map);

        Collection<String> collection = map.values();
        for (String value : collection) {
            System.out.println(value);
        }
    }

}

{1=张三, 2=李四, 3=王五}
张三
李四
王五

3、使用entrySet方法,这个方法可以将 Map 中所有的键值对就是以成对的形式放入 Set 中。这个方法的返回值是Set<Map.Entry<K, V>>,这个Map.Entry<K, V>java.util.Map中的一个内部接口。

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

public class MapTest {

    public static void main(String[] args) {
        Map<Integer, String> map = new HashMap<>();

        map.put(1, "张三");
        map.put(2, "李四");
        map.put(3, "王五");
        System.out.println(map);

        Set<Map.Entry<Integer, String>> set = map.entrySet();
        for (Map.Entry<Integer, String> entry : set) {
            System.out.println(entry.getKey() + "=" + entry.getValue());
        }
    }

}

{1=张三, 2=李四, 3=王五}
1=张三
2=李四
3=王五

3、HashMap 放入元素的大概过程

  • 之前提到过java.util.HashSet的本质上是java.util.HashMap,所以,对于向java.util.HashMap中放入元素的过程是和java.util.HashSet是相似的,只不过,在这个过程中一系列的计算是基于元素中那个作为“键”的对象。
HashMap 放入元素大致过程
  • 对于哈希表这个数据结构而言,一般情况是“数组+链表”这样的一种形式,但是在 Java 的 HashMap 中,为了提高查询效率,在一定条件下,“数组+链表”的形式会变为“数组+红黑树”的形式。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354