查缺补漏day

一、HashMap

1.HashMap :
    基于哈希表的Map接口的实现。 此实现提供了所有可选的映射操作,并允许null值和null键。
    HashSet 底层是由HashMap
    底层结构 : 哈希表(数组+链表+红黑树)

2.哈希表:
      数组 : 节点数组Node[] --> 要求数组的长度为2的整数次幂
        Node : int hash,Object key,Object value,,Node next
      每个索引位置存储的为一个单向链表的首节点(尾插法)
      当链表的长度>8,数组的长度>64,会把链表优化成为红黑树
        当链表的长度>8,但是数组的长度不大于64,这时候会实现扩容(数组的扩容)
3.初始容量: 哈希表中的数组默认的初始长度  16
    static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16
    数组的容量最大容量 : static final int MAXIMUM_CAPACITY = 1 << 30;
4.加载因子: 0.75 一般不建议改变
    默认加载因子 : static final float DEFAULT_LOAD_FACTOR = 0.75f;
5.扩容阀值 threshold  : 扩容的临界值  数据的个数size>数组的长度*加载因子 就会扩容
6.扩容机制: 原容量的2倍 int newCap = oldCap << 1

7.新增功能: 无

8.HashMap的哈希表存储数据的过程:
   (1).根据key计算哈希值
        通过key的hashCode方法的返回值进一步进行hash算法的运算,得到的整数
        int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);

    (2).调用putVal方法实现添加数据(hash,key,value)
        1)判断是否是第一次调用put方法做添加 if ((tab = table) == null || (n = tab.length) == 0)
          如果是第一次添加,直接调用resize()实现扩容
        2)计算位桶的索引 int index = (n - 1) & hash
        3)判断哈希表结构的数组table[index]是否存在数据,
            如果不存在数据,证明没有头节点,创建新节点,放入当前数组的对应索引位置作为头节点
                table[index] = new Node<>(hash, key, value, next);
                size数据的个数+1,判断是否>扩容的阀值,如果大于需要调用resize方法进行扩容,如果不大于,不需要扩容直接返回null
                if (++size > threshold) resize();
                return null;
            如果存在数据,作为链表的头结点,遍历这个链表,拿到每一个节点的key与hash值判断是否与要添加的key和hash相同,如果相同,value覆盖
                if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
                value覆盖之后,返回被覆盖的value
                V oldValue = e.value;
                e.value = value;
                return oldValue;
去重 : 根据key做去重,要求key的数据类型重写hashCode与equals方法

测试: 定义HashMap存储数据,要求key为javabean,实现去重与测试

二、HashTable

1.Hashtable 与 HashMap之间的区别:
    共同点 : 都是Map接口的实现类,底层结构都是哈希表
    异同点 :
        (1)继承体系不同
        (2)线程是否安全不同
            HashMap 线程不安全|不同步
            Hashtable 线程安全的|同步的
        (3)扩容机制不同
            HashMap扩容机制 : 每次扩容原容量的2倍
                int newCap = oldCap << 1
            Hashtable扩容机制 : 原容量的2倍+1
                int newCapacity = (oldCapacity << 1) + 1;
       (4).键值对数据null值的要求不同
            HashMap 可以存储null值的key与value
            Hashtable key与value都不为null

       (5)计算hash值与位桶索引index的算法不同
            HashMap :
                int hash = (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
                int index = (n - 1) & hash
            Hashtable :
                int hash = key.hashCode();
                int index = (hash & 0x7FFFFFFF) % tab.length;

2. 如何处理HashMap线程不安全问题:
   (1)使用Hashtable
   (2)使用Collections工具类中static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) 返回由指定映射支持的同步(线程安全)映射。
    (3)juc高级并发编程包 ConcurrentHashMap<K,V>-> 线程安全的哈希表
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值