HashMap小结

踏踏实实积累,不要浮躁!!!

1:为什么用HashMap

  • HashMap 是一个散列桶(数组和链表),它存储的内容是键值对(key - value)
  • HashMap采用了数组和链表的数据结构,能在查询和修改方面继承了数组的线性查找和链表的寻址修改
  • HashMap是线程不安全的
  • HashMap可以接受null键和值,而HashTable不能

解释为什么 HashMap可以接受 null 键和值

a:如果 k 值传入的是 null ,得到的hash 值是0

b:解析 HashMap put的源码逻辑   TODO

 

 

2:HashMap工作原理 ?

HashMap是基于hashing的原理,我们使用put(key,value)存储对象到HashMap中,使用 get(key)从HashMap中获取对象,调用Put方法时通过key的hashcode值找到Map数组的bucket位置来存储Node对象,具体流程如下

  • 1:对key求Hash值,然后计算下标
  • 如果没有碰撞直接放入桶中
  • 如果发生碰撞,以链表的方式放在后面(用链表法来解决冲突)
  • 如果链表长度超过阀值  TREEIFY_THRESHOLD(8) 会改造成 rbTree 当元素个数小于6的时候又转换成链表
  • 如果节点已经存在,会替换原来的value值
  • 如果 桶满了(初始容量16 * 负载因子0.75)就需要 resize操作 扩容到之前的两倍 

3:有什么方法可以减少碰撞

  • 扰动函数可以减少碰撞,尽量确保两个不相等的对象返回不同的hashcode,这样能减少碰撞的几率(扰动函数其实就是Hash函数内部的实现原理 TODO 里面具体的实现细节还不清楚)
  • 使用不可变的,声明为final的对象做key,并且采用合适的hashcode和equals方法,在hashmap中Keyi值不可变是必要的

4:HashMap中 hash函数的实现

static final int hash(Object key) {
    if (key == null){
        return 0;
    }
     int h;
     h=key.hashCode();返回散列值也就是hashcode
      // ^ :按位异或
      // >>>:无符号右移,忽略符号位,空位都以0补齐
      //其中n是数组的长度,即Map的数组部分初始化长度
     return  (n-1)&(h ^ (h >>> 16));
}

解释:

1:求出key的hash值

2:将hash值高16位不变,低16位与高16位取异或

3:n表示桶的长度,通过(n -1) & 上面取的值 得到桶的序号  (其实就是取模这种方式更高效)

 

5:为什么不用二叉查找树,而用红黑树

红黑树可以解决 二叉查找树,在特殊情况下性能退化的问题(可能会退化成链表,查找的时间复杂度O(n)),

 

6:说说你对红黑树的见解

  • 每个节点非黑即红
  • 根节点是黑色的
  • 如果节点是红色的,那么子节点一定时黑色的,反之不一定
  • 每个叶子节点都是黑空
  • 从根节点到叶子节点的路径,每条路径都包涵数目相同的黑色节点(黑色高度相同)

 

7:HashMap什么情况下会发生死循环

TODO

 

 

 

8:CurrentHashMap 原理

 

  • 最大的特点是引入了 CAS (compare and swap)借助Unsafe来实现,采用cpu指令来保证 (CAS操作的过程,内存值V,旧的预期值A,要修改的新值B 当且仅当预期值A和内存值V相等时才会将B值更新到V值中去)
  • 分段锁   降低了锁的粒度
  • TODO

TODO

9:CAS操作会出现的问题

TODO

 

 

 

10:能用currenthashmap代替hashtable嘛 ?

可以的

 

 

11:currenthashmap在java8中有个bug,会进入死循环

原因是递归创建currenthashmap对象,该bug在1.9已经修复

场景重现如下

public class ConcurrentHashMapDemo{

    private Map<Integer,Integer> cache =new ConcurrentHashMap<>(15);

    public static void main(String[]args){
        ConcurrentHashMapDemo ch =    new ConcurrentHashMapDemo();
        System.out.println(ch.fibonaacci(80));
    }

    public int fibonaacci(Integer i){
        if(i==0||i ==1) {
            return i;
    }

    return cache.computeIfAbsent(i,(key) -> {
        System.out.println("fibonaacci : "+key);
        return fibonaacci(key -1)+fibonaacci(key - 2);
    });

    }
}

TODO 原因解释  ??? 

 

12: JDK9怎么解决上面这个死循环的BUG ?

 

 

 

 

 

 

 

内容概要:本文系统介绍了算术优化算法(AOA)的基本原理、核心思想及Python实现方法,并通过图像分割的实际案例展示了其应用价值。AOA是一种基于种群的元启发式算法,其核心思想来源于四则运算,利用乘除运算进行全局勘探,加减运算进行局部开发,通过数学优化器加速函数(MOA)和数学优化概率(MOP)动态控制搜索过程,在全局探索与局部开发之间实现平衡。文章详细解析了算法的初始化、勘探与开发阶段的更新策略,并提供了完整的Python代码实现,结合Rastrigin函数进行测试验证。进一步地,以Flask框架搭建前后端分离系统,将AOA应用于图像分割任务,展示了其在实际工程中的可行性与高效性。最后,通过收敛速度、寻优精度等指标评估算法性能,并提出自适应参数调整、模型优化和并行计算等改进策略。; 适合人群:具备一定Python编程基础和优化算法基础知识的高校学生、科研人员及工程技术人员,尤其适合从事人工智能、图像处理、智能优化等领域的从业者;; 使用场景及目标:①理解元启发式算法的设计思想与实现机制;②掌握AOA在函数优化、图像分割等实际问题中的建模与求解方法;③学习如何将优化算法集成到Web系统中实现工程化应用;④为算法性能评估与改进提供实践参考; 阅读建议:建议读者结合代码逐行调试,深入理解算法流程中MOA与MOP的作用机制,尝试在不同测试函数上运行算法以观察性能差异,并可进一步扩展图像分割模块,引入更复杂的预处理或后处理技术以提升分割效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值