讲一下map,讲一下HashMap吧
答:Map是一种专门用来搜索的数据结构,它经常用来存放键值对。Map允许我们在查找的时候进行插入和删除操作,这使得它在处理这类任务时非常高效。Map的使用与其实例的子类有关,因此不同的Map实现可能会有不同的搜索效率。
HashMap是Map接口的一个实现类,它主要适用于插入、删除和定位元素的操作。HashMap基于哈希表实现,它利用哈希函数(如hashCode())将键(key)转化为数组的索引(index),然后根据这个索引来存储和查找键值对。这种机制使得HashMap在插入、删除和定位元素时具有非常高的效率。
然而,HashMap并不保证键的顺序,也就是说,遍历HashMap可能会得到不同的顺序结果,除非在特定的构造器中进行排序。如果需要有序的遍历,那么可能会选择其他类型的Map,比如TreeMap。
当不同的键通过哈希函数运算得到相同的索引时,就会发生哈希碰撞(或哈希冲突)。HashMap通过链表或红黑树(在Java 8及以后的版本中,当链表长度超过一定阈值时,链表会转化为红黑树)来解决这种冲突,这种策略被称为拉链法。
你说到了链表长度为8的时候会转换为红黑树,为什么是8呢?
答:当HashMap中的某个桶(bucket)的链表长度达到8时,会触发树化(treeifyBin)操作,将链表转换为红黑树。这是为了优化性能,因为红黑树的查找、插入和删除操作的时间复杂度都是O(log n),而链表在长度较长时的这些操作的时间复杂度为O(n)。当桶中的元素数量较少时,链表操作已经足够高效,因此没有必要转换为红黑树。
另外,链表长度超过8并不是唯一触发树化的条件。还有一个条件是桶的总数超过64。也就是说,如果HashMap中的桶的总数超过64,并且某个桶的链表长度达到8,那么链表就会转换为红黑树。这是为了避免过多的树化操作,因为红黑树的空间占用相对于链表来说要大一些。
至于为什么选择8和64这两个数字,它们是通过实验和性能测试得出的经验值。这些值在大多数情况下都能提供较好的性能和空间使用效果。当然,具体的实现可能会因Java版本的不同而有所差异,但背后的设计思想和权衡是相似的。
HashMap为什么线程不安全?
答:
扩容:当HashMap中的元素数量超过其容量时,会触发扩容操作。这个操作涉及到生成新的数组、重新计算原有键值对的位置,并写入新的数组。如果在多线程环境下,多个线程同时检测到需要扩容并尝试执行resize操作,这可能导致数据不一致、死循环或死锁。例如,某些线程可能已经完成赋值,而其他线程刚开始赋值,这样就可能用已经被赋值的table作为原始数组,从而导致问题。
put和get操作的非原子性:在HashMap中,put和get操作并不是原子性的。这意味着在多线程环境下,一个线程可能正在执行put操作(包括计算哈希值、确定索引和存储键值对等步骤),而另一个线程可能同时执行get操作,这可能导致get到的值并不是最新的或者预期的值。
删除操作的问题:当在HashMap中删除某个键值对时,实际上是删除了该键值对在内部数组中的对应位置。如果有多个线程同时尝试删除不同的键值对,它们可能会相互干扰,导致数据不一致。
线程池参数有哪些?
答:线程池的参数主要包括以下几个方面:
corePoolSize:线程池中的常驻核心线程数。这些线程在创建线程池后就会立即启动,即使它们当前并没有任务执行。
maximumPoolSize:线程池能够容纳同时执行的最大线程数。当工作队列已满,并且正在执行的线程数达到这个值时,线程池就不会再创建新的线程。这个值必须大于等于1。
keepAliveTime:多余的空闲线程的存活时间。当线程池中的线程数超过corePoolSize,并且这些多余的线程在keepAliveTime这段时间内没有执行任务,那么它们就会被销毁,直到线程池中的线程数减少到corePoolSize为止。
unit:keepAliveTime的单位,比如可以是TimeUnit.SECONDS、TimeUnit.MILLISECONDS等。
workQueue:任务队列。当线程池中的线程都在忙时,新提交的任务会存放在这个队列中等待执行。
threadFactory:线程工厂,用于创建新的线程。一般情况下,我们可以使用默认的线程工厂,但如果需要自定义线程的创建方式,比如设置线程名、设置线程优先级等,就需要使用自定义的线程工厂。
handler:拒绝策略。当队列已满,并且线程池中的线程数已达到maximumPoolSize时,如果还有新的任务提交,就需要根据这个策略来处理这个新任务。常见的拒绝策略有:直接抛出异常、使用调用者的线程来运行任务、丢弃这个任务、丢弃队列中最老的任务然后尝试提交新任务等。
怎么关闭线程池?
shutdownNow()为什么有些任务无法取消?
TreadLocal是干嘛的?原理是什么?
ThreadLocal会导致什么问题?
synchronized 和 ReentrantLock 有什么区别?
ReentrantLock是怎么实现的?AQS?讲一下AQS?他是怎样获取锁的?
Semaphore和CountDownLatch有了解过吗?
讲一下Java有哪些IO模型
你知道select和epoll有什么区别吗?
零拷贝有哪些实现方式?
用过Java哪些框架?springboot是用来解决什么问题的?spring呢?
说一下jvm内存区域划分
说一下本地方法栈和java虚拟机栈的关系
一个啥啥啥String语句***它的各部分在内存的哪?当时没听明白,应该是想问字符串常量池和堆
还有一个啥啥啥是怎么加进jvm内存的,也没听懂。说了下类加载过程。又问就是这个class文件pilipala***
有做过jvm调优吗?
垃圾回收算法有哪些?
了解哪些最新的垃圾回收器?
MySQL有哪些锁?
事务有哪些隔离级别
readview是干嘛的?
除了可重复读就没别的地方使用readview了吗?
ReadView的结构。这三个问题他都想引导我说undolog,没反应过来。
宕机了,redolog是怎么保证持久性的?
binlog和redolog的区别?
如何实现binlog和redolog的同步?
讲一下zookeeper的底层原理
除了ZAB,还知道哪些分布式一致性协议?
拷打项目
你这个项目,还有什么别的实现方式吗?
说一下你对最终一致性和强一致性的理解
既有最终一致性又有强一致性不会冗余吗?
消息队列里面怎么保证一致性?
为什么会想要自己实现一个rpc?
手撕 lc287 寻找重复数
上来就拷打了五十分钟八股,人已经面麻了