Map接口-实现类HashMap

目录

一、什么是Map?

二、实现类HashMap

1.关键特点

无序、key唯一、value允许重复、key和value允许为null。

2.数据结构

[2.1 JDK 1.7](#2.1 JDK 1.7)

[2.2 JDK 1.8](#2.2 JDK 1.8)

[2.3 关键参数](#2.3 关键参数)

[2.4 关键计算](#2.4 关键计算)

3.扩容方式

[3.1 初始化](#3.1 初始化)

[3.2 扩容](#3.2 扩容)

4.常见方法

[4.1 根据key存入value](#4.1 根据key存入value)

[4.2 根据key获取value](#4.2 根据key获取value)

[4.3 判断Map](#4.3 判断Map)

[4.4 根据key替换value](#4.4 根据key替换value)

[4.5 根据key删除value](#4.5 根据key删除value)

[4.6 遍历Map](#4.6 遍历Map)


一、什么是Map?

(1)Map是一种键值对集合,每一个元素都包含一个 键对象(key) 和一个 值对象(value)。

(2)Map集合中,键不允许重复,值可以重复。 (比如身份证与姓名)

(3)键和值是一一对应的,通过键可以找到与之对应的唯一的值。

(4)key和value必须是引用数据类型。

二、实现类HashMap

1.关键特点

无序、key唯一、value允许重复、key和value允许为null。

2.数据结构

2.1 JDK 1.7

数组+单向链表

在链表中插入元素,采用【头插法】

2.2 JDK 1.8

数组+单向链表+红黑树

在链表中插入元素时,采用【尾插法】

2.3 关键参数

(1)Node<K, V>[ ] table:

保存KV键值对的数组,每个KV键值对都被封装成一个Node对象。

数组容量决定了HashMap对内存的占用大小。

(2)float loadFactor:

加载因子(填充因子)。

加载因子默认为0.75,代表HashMap对数组容量的使用率为75%,超过该使用率,则数组需要进行扩容。

加载因子决定了HashMap对数组的使用率,加载因子越高,则表示允许填满的元素就越多,集合的空间利用率就越高,但是冲突的机会增加。反之,越小则冲突的机会就会越少,但是空间很多就浪费。

(3)int threshold:

扩容阈值。

用于判断数组是否需要进行扩容。

扩容阈值threshold = 数组容量 × 加载因子。

(4)size : int

KV键值对的数量。

2.4 关键计算

(1)hash()函数:

(h = key.hashCode()) ^ (h >>> 16):在key原有哈希值的基础上,与哈希值的高16位进行异或运算,计算出的哈希值更佳散列,不易出现哈希冲突。

(2)下标计算:JDK 1.7 :hash % 数组长度。

JDK 1.8:(数组长度 - 1) & hash。提高性能--数组长度必须为2的N次幂。

3.扩容方式

3.1 初始化

(1)public HashMap():加载因子默认为为0.75。

(2)public HashMap(int initialCapacity, float loadFactor):指定容量和加载因子。

3.2 扩容

(1)添加第一个KV键值对,数组如果为空,则默认扩容为16。

(2)加入元素时,如果链表长度大于阈值(默认为 8)并且数组长度小于64,会产生数组扩容;*2。

(3)添加元素后,当HashMap中的元素个数超过【数组大小 × 加载因子(LoadFactor)】时,原数组扩容2倍。例如:加载因子(LoadFactor)的默认值为0.75,数组容量默认为16,当HashMap中元素个数超过16 × 0.75=12的时候,数组的容量扩容为16×2 =32;

4.常见方法

4.1 根据key存入value

(1)V put(K key, V value):存入【KV键值对】,如果key存在,则覆盖【原value值】,保存后,返回【原value值】。

(2)void putAll(Map m):将【指定map】中的所有KV键值对,存入【当前map】。

(3)V putIfAbsent(K key, V value):如果key不存在,则保存value,并返回【null】;如果key已经存在,则不保存value,并返回【原value值】。

4.2 根据key获取value

(1)V get(Object key):根据key,返回【value值】;如果key不存在,则返回【null】。

(2)V getOrDefault(Object key, V defaultValue):根据key,返回【value值】;如果key不存在,则返回【默认值】。

4.3 判断Map

(1)boolean containsKey(Object key):判断key是否存在。

(2)boolean containsValue(Object value):判断value是否存在。

(3)boolean isEmpty():判断map中的【KV键值对】数量是否为0。

(4)int size():获取map中的【KV键值对】数量。

4.4 根据key替换value

(1)V replace(K key, V value):根据key,替换value,并返回【原value值】;如果key不存在,则返回【null】。

(2)boolean replace(K key, V oldValue, V newValue):根据key和value,替换value,修改成功,返回【true】;如果key和value不存在,则替换失败,返回【false】。

4.5 根据key删除value

(1)V remove(Object key):根据key,删除【KV键值对】,并返回【原value值】。

(2)boolean remove(Object key, Object value):根据key和value,删除【KV键值对】,则删除成功,返回【true】;如果key和value不存在,则删除失败,返回【false】。

(3)clear():清除map中的键值对。

4.6 遍历Map

(1)Set<K> keySet():获取所有key。

(2)Collection<V> values():获取所有value。

(3)Set<Map.Entry<K,V>> entrySet():获取所有【KV键值对】,每个【KV键值对】使用【Entry类型的对象】封装。

java 复制代码
public class Demo01 {
    public static void main(String[] args) {
        //HashMap 无序,且key是唯一的,value是可重复的
        HashMap<String,String> hashMap=new HashMap<>();
        hashMap.put("110","北京");
        hashMap.put("120","天津");
        hashMap.put("130","河北");
        hashMap.put("610","陕西");
        hashMap.put("610","甘肃");
        hashMap.put("620","甘肃");
        System.out.println(hashMap);
    }
}
java 复制代码
public class Demo02 {
    public static void main(String[] args) {
        HashMap<String, String> hashMap = new HashMap<>();
        insertElement(hashMap);
        //selectElement(hashMap);
        deleteElement(hashMap);
    }
    public static void insertElement(HashMap<String, String> hashMap) {
        System.out.println("========进入到添加方法中========");
        //1.V put(K key, V value)存键值对,如果集合不存在此键,直接存,返回值为null
        //当存在此键时,返回值为上一次的键对应的value,用此value覆盖
        String item1 = hashMap.put("110", "北京");
        String item2 = hashMap.put("110", "天津");
        hashMap.put("130", "河北");
        hashMap.put("610", "陕西");
        System.out.println("第一次存返回值:" + item1);
        System.out.println("第二次存返回值:" + item2);

        //void putAll(Map m)
        HashMap<String, String> hashMap1 = new HashMap<>();
        hashMap1.put("620", "甘肃");
        hashMap1.put("630", "宁夏");
        hashMap1.put("610", "内蒙");
        //将指定map中的所有KV键值对,存入到当前map;
        hashMap.putAll(hashMap1);
        System.out.println(hashMap);

        //V  putIfAbsent(K key,V value)如果存在此键,返回值为键对应的旧值,如果不存在则存返回null
        String oldValue = hashMap.putIfAbsent("611", "西安");
        System.out.println("putIfAbsent再次存610的键:" + oldValue);
        System.out.println(hashMap);
    }

    public static void selectElement(HashMap<String, String> hashMap) {
        System.out.println("=======进入到查看方法中=======");
        System.out.println("目前map中的元素为:" + hashMap);

        //V get(Object key)根据key,返回value值,如果key不存在,则返回null
        String value1 = hashMap.get("120");
        System.out.println("键120对应的值为" + value1);

        //V getOrDefault(Object key,V defaultValue)
        //根据key,返回value值,如果key不存咋,则返回默认值
        String value2 = hashMap.getOrDefault("120", "不知道");
        System.out.println("键120对应的值为:" + value2);

        //boolean containsKey(Object key)判断key是否存在
        boolean b1 = hashMap.containsKey("611");
        System.out.println("键611是否存在:" + b1);

        //boolean containsValue(Object value)判断value是否存在
        boolean b2 = hashMap.containsValue("宁夏");
        System.out.println("值宁夏是否存在:" + b2);

        //boolean isEmpty()判断map中的【KV键值对】数量是否为0
        System.out.println("集合map是否为空:" + hashMap.isEmpty());

        //int size()获取map中的【KV键值对】数量
        System.out.println("集合的size:" + hashMap.size());

    }

    public static void deleteElement(HashMap<String, String> hashMap){
        System.out.println("========进入到删除和修改方法中========");
        System.out.println("目前map中的元素为:" + hashMap);
        //V replace(K key, V value)根据key,替换value,并返回【原value值】;如果key不存在,则返回【null】
        String value=hashMap.replace("110","北京");
        System.out.println(value);
        System.out.println("修改后的hashmap:"+hashMap);
        //boolean replace(K key, V oldValue, V newValue)
        //根据key和value,替换value,修改成功,返回【true】;如果key和value不存在,则替换失败,返回【false】;
        boolean b1=hashMap.replace("610","内蒙","陕西");
        System.out.println(b1);
        System.out.println("修改后的hashmap:"+hashMap);
        //V remove(Object key)根据key,删除【KV键值对】,并返回【原value值】
        String str=hashMap.remove("130");
        System.out.println(str);
        System.out.println("删除后的hashmap:"+hashMap);
        //boolean remove(Object key, Object value)
        //根据key和value,删除【KV键值对】,则删除成功,返回【true】;如果key和value不存在,则删除失败,返回【false】;
        boolean b2=hashMap.remove("630","陕西");
        System.out.println(b2);
        System.out.println("删除后的hashmap:"+hashMap);
        //clear()
        hashMap.clear();
        System.out.println("清空后:"+hashMap);
    }
}
java 复制代码
public class Demo03 {
    public static void main(String[] args) {
        HashMap<String,String> hashMap=new HashMap<>();
        hashMap.put("110","北京");
        hashMap.put("120","天津");
        hashMap.put("130","河北");
        hashMap.put("610","陕西");
        hashMap.put("620","甘肃");
        System.out.println(hashMap);

        //1.Set<K> keySet()获取所有的键
        Set<String> keys = hashMap.keySet();
        for (String key : keys) {
            String value = hashMap.get(key);
            System.out.printf("键为:%s - 值为%s\n", key, value);
        }
        //2.获取所有的value Collection<V> values()
        Collection<String> values = hashMap.values();
        System.out.println(values);
        //3.获取所有的键值对集合对象
        Set<Map.Entry<String, String>> entries = hashMap.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey() + "==" + entry.getValue());
        }
    }
}