Java集合详解2——HashMap接口的介绍以及HashMap存储数据的原理

一、Map集合的概述

1、概述:

        Map接口是Java集合框架中的一种用于存储键值对映射关系的接口。interface Map<K,V> 其中K是键的类型,键是唯一的,不重复。V是值的类型,是可以重复。且每个键可以映射最多一个值。注意的是如果存在两个相同的键时,则会将现在的值替换之前的值。key 和 value 都可以是任何引用类型的数据。Map 的 key 不允许重复,value 可以重复,

  • 即同一个 Map 对象的任何两个 key 通过 equals 方法比较总是返回 false。

Map 中的 key 和 value 之间存在单向一对一关系,即通过指定的 key,总能找到唯一的、确定的 value。从 Map 中取出数据时,只要给出指定的 key,就可以取出对应的 value。

Map 接口主要有两个实现类:HashMap 类和 TreeMap 类,这里先看HashMap类。

创建方式:以多态的形式创建对象。

Map<String, Integer> hashMap = new HashMap<>();

HashMap的继承实现结构图以及HashMap的构造方法: 

2、特点:

  • 键值对映射关系
  • 一个键对应一个值
  • 键不能重复,值可以重复
  • 元素存取无序
  • 允许空键值:Map中允许使用null 作为键和 值。

在此,我会列出Map集合中的一些常用方法,并对这些方法进行代码的实现

二、java.util.Map接口中的常用方法

1、Map集合以key和value的方式存储数据:键值对方式

  • key和value都是引用数据类型。

  • 都是存储对象的内存地址

  • Interface Map<K,V>

      • 参数类型

        K - 此映射维护的密钥类型

        V - 映射值的类型

2、Map接口中常用的方法:

第一个方法:向Map集合中添加键值对 

V put(K key, V value)

第二个方法:返回指定键映射到的值通过key获取value ,若没有获取到则返回null

V get(Object key)

第三个方法:从此映射中删除所有映射(可选操作)。 清空Map集合

void clear()

第四个方法:判断Map是否包含某个key, 如果此映射包含指定键的映射,则返回true。

boolean containsKey(Object key)
参数 :key - 要测试其在此Map中是否存在

第五个方法:判断Map是否包含某个value

boolean containsValue(Object value)

第六个方法:判断Map中元素个数是否为0

boolean isEmpty()
获取Map集合中键值对的个数:
int size()

第七个方法:获取Map集合中所有的key(所有的键都是一个“Set集合”)

Set<K> keySet()
返回此映射中包含的键的Set视图。

第八个方法:通过key删除键值对

V remove(Object key)
如果存在,则从该映射中移除键的映射(可选操作)。
default boolean  remove(Object key, Object value)
仅当指定键当前映射到指定值时,才删除该条目。

第十个方法:获取Map集合中所有的value,返回一个“Collection”

Collection<V> values()

第十一个方法:将Map集合转换成一个Set集合

Set<Map.Entry<K,V>> entrySet()

注意:【Map集合通过entrySet()方法转换成的这个Set集合,Set集合中的元素的类型是Map.Entry<K,V>】

【Map.Entry和String一样,都是一种类型的名字,只不过:Map.Entry是静态内部类,是Map中的静态内部类】

第十二个方法:返回指定键映射到的值,如果此映射不包含该键的映射,则返回 defaultValue。

default V getOrDefault(Object key, V defaultValue)

第十三个方法:仅当指定键当前映射到某个值时才替换该条目。

default V  replace(K key, V value)
仅当指定键当前映射到指定值时,才删除该条目:
default boolean replace(K key, V oldValue, V newValue)

3、Map集合的常用方法代码实现:

import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class test{
    public static void main(String args[]) {
        //创建Map集合
        Map<Integer,String> myMap = new HashMap<>();
        //向集合中添加键值对
        myMap.put(2,"abc");
        myMap.put(3,"张三");
        myMap.put(4,"李四");
        myMap.put(5,"老六");
        //通过key获取value
        String ss = myMap.get(5);
        System.out.println(ss);     //老六

        System.out.println("获取键值对的数量:"+myMap.size());//获取键值对的数量:4
        //通过key删除key-value
        myMap.remove(2);
        System.out.println(myMap.size()+"对");           //3对
        //判断Map是否包含某个key
        System.out.println(myMap.containsKey(2));           //false
        //判断Map是否包含某个value
        System.out.println(myMap.containsValue("张三"));      //true
        myMap.clear();
        System.out.println("获取键值对的数量:"+myMap.size());//获取键值对的数量:0
        System.out.println(myMap.isEmpty());      //true
        //创建Map集合
        Map<Integer,Integer> myMap2 = new HashMap<>();
        //向集合中添加键值对
        myMap2.put(2,9);
        myMap2.put(3,8);
        myMap2.put(4,4);
        myMap2.put(5,2);
        //获取所有的value
        Collection<Integer> value = myMap2.values();
        for (Integer i:value) {
            System.out.println(i);/*9
                                    8
                                    4
                                    2*/
        }
    }
}

三、HashMap存储数据的原理(put的流程)

JDK1.8 之后HashMap底层是数组 + 链表 + 红黑树。

HashMap 的存值过程:

(1) 根据 key 计算hash值。在put 的时候判断数组是否存在,如果不存在则用resize() 方法创建默认长度为16的数组。
(2) 确定要存入的 Node 在数组中的位置,根据 hash 值与数组最大索引进行按位与运算得到索引位置。
(3) 判断该位置是否有元素,如果没有直接创建一个 Node 存入。如果有元素,判断 key 是否相同,如果相同则覆盖,并且将原来的值直接返回。如果key 不相同,在原Node基础上添加新的Node,判断该位置是链表还是红黑树。
(4) 如果是红黑树,将 Node 存入红黑树。
(5) 如果是链表,遍历链表,找到最后一位,将 Node 存入。
(6) 将 Node 存入链表之后,判断链表的结构是否要调整,判断链表长度是否超过8,如果超过8,需要将链表转为红黑树,这里还有一个条件,如果数组的容量小于64,不转换红黑树,而是进行数组扩容,当数组的容量大于64的时候,再将链表转为红黑树。
(7)存完之后,再次判断数组是否进行扩容,根据负载因子来判断。

  • 删除元素时,如果时以红黑树存储的如果节点小于 6 个将会变为链表存储

关于红黑树的介绍参考点击这里

支持:🎁🎁🎁如果你觉得博主的文章的不错或者对你有帮助,可以点一个免费的关注支持一下博主,如果三连收藏支持就更好了吖,嘿嘿嘿,蟹蟹。 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

-今非昔比°

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值