[Java学习笔记]Map下的映射表

接口 Map<K,V>

  • 类型参数: K - 此映射所维护的键的类型 V - 映射值的类型
    因为Map中的Entry键值对、Key键都是有Set存放的,这也就确保了键、键值对是不可重复的(Value可重复)

public interface Map<K,V>
将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。

在这里插入图片描述
常用方法

  1. void clear()
    从此映射中移除所有映射关系(可选操作)。

  2. boolean containsKey(Object key)
    如果此映射包含指定键的映射关系,则返回 true。

  3. boolean containsValue(Object value)
    如果此映射将一个或多个键映射到指定值,则返回 true。

  4. Set<Map.Entry<K,V>> entrySet()
    返回此映射中包含的映射关系的 Set 视图。

  5. boolean equals(Object o)
    比较指定的对象与此映射是否相等。

  6. V get(Object key)
    返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。

  7. boolean isEmpty()
    如果此映射未包含键-值映射关系,则返回 true。

  8. Set keySet()
    返回此映射中包含的键的 Set 视图。

  9. V put(K key, V value)
    将指定的值与此映射中的指定键关联(可选操作)。

  10. void putAll(Map<? extends K,? extends V> m)
    从指定映射中将所有映射关系复制到此映射中(可选操作)。

  11. V remove(Object key)
    如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。

  12. int size()
    返回此映射中的键-值映射关系数。

  13. Collection values()
    返回此映射中包含的值的 Collection 视图。

HashMap

基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。

构造方法摘要

  1. HashMap()
    构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap。
  2. HashMap(int initialCapacity)
    构造一个带指定初始容量和默认加载因子 (0.75) 的空 HashMap。
  3. HashMap(int initialCapacity, float loadFactor)
    构造一个带指定初始容量和加载因子的空 HashMap。
  4. HashMap(Map<? extends K,? extends V> m)
    构造一个映射关系与指定 Map 相同的新 HashMap。

HashMap的底层实现结构——链表数组(Node<K,V>[] table)

Java中的HashMap的基本结构就如上图所示,竖着看是一个数组,横着看就是多个链表。当新建一个HashMap的时候,就初始化了一个数组:
如上图;Java中的HashMap的基本结构就如上图所示,竖着看是一个数组,横着看就是多个链表。当新建一个HashMap的时候,就初始化了一个数组。

存储方式:HashMap在存储时存储方式与HashSet基本一致:首先它在put方法执行时,通过Key计算出其哈希码,并由此确定该键值对存放位置,倘若该位置为空则直接存入,否则使用key的Equals方法与该位置元素对比,若为同一个key那么替换该键值对,否则遍历该键值对对应链表寻找相同key直至表尾直接存放该新键值对!

思考:那么我们在添加的过程中如果空间较小,很容易出现不同key对应同一位置需要放置于链尾,
这就造成一个问题,链表可能很长!——我们在使用get方法获取键值对的时候需要的复杂度会非常高!那么就要让链表部分尽量短,也就是空间要相对大,如何实现呢?

  • 通过对table数组部分扩容以减少产生长链的可能,并且在扩容的时候对所有键值对重新计算位置以保持整个HashMap中链部分相对较少,但是扩容时需要重新计算Hashcode又使得计算量增大,那么我们何时选择扩容呢?显然等到数组满了才扩容是非常愚蠢的,因为等待数组满了,链表早已经长的夸张了!于是我们规定了加载因子loadFactor(默认0.75),当数组空间被占用75%时就自动成倍扩容空间。

下面是Jdk1.8中的put方法实现

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
   
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)//首次存储位置为空则直接存放即可
            tab[i] = newNode(hash, key, value, null);
        else {
   
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))//碰到了相同key的键值对
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).<
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值