java基础

面试-java基础

集合-高频面试题

img编辑

HashMap 在JDK1.7 和JDK1.8 中差别

  1. 数据结构

    • JDK 1.7:HashMap在JDK 1.7中是基于数组和链表的实现。当发生哈希冲突时,会使用链表头插来解决冲突。

    • JDK 1.8:HashMap在JDK 1.8中引入了红黑树(Red-Black Tree)来优化链表。当链表长度超过一定阈值(默认为8,并且数组长度大于64,否则会先扩容)时,链表会转换为红黑树,以提供更快的查找、插入和删除操作。

  2. 插入和扩容时的顺序

    • JDK 1.7:在插入新元素或扩容时,HashMap会重新计算元素的hash值,并根据新的hash值重新定位元素在数组中的位置。这个过程可能导致元素的顺序发生变化,尤其是在并发环境下,可能导致链表成环的问题。

    • JDK 1.8:JDK 1.8优化了插入和扩容时的顺序问题。扩容时,HashMap会尽量保持原有链表的顺序(倒数第五位的值是0,下标不变,倒数第五位的值是1,原来下标的2倍),并且新插入的元素会被放到链表的尾部,从而避免了链表成环的问题。

  3. hash值的计算

    • JDK 1.7:hash值的计算采用了9次扰动(4次位运算+5次异或运算),并且hash值在插入后不可改变。

    • JDK 1.8:hash值的计算采用了2次扰动(1次位运算+1次异或运算),并且hash值在插入后不可改变(final修饰)。这种变化减少了hash计算的复杂性,提高了性能。

  4. 扩容策略

    • JDK 1.7:HashMap在扩容时会先创建一个新的数组,然后将原数组中的元素重新计算hash值并插入到新数组中。这个过程可能导致大量的数据迁移和重定位。

    • JDK 1.8:HashMap在扩容时采用了更优化的策略。如果原数组容量未达到64,则直接扩容2倍;如果原数组容量超过64,且链表长度大于8,则将链表转换为红黑树;如果红黑树中的元素个数小于6,则红黑树会还原为链表。这种策略在保持性能的同时,减少了数据迁移和重定位的开销。

  5. 并发控制

    • JDK 1.7:HashMap本身不是线程安全的,需要外部同步措施来确保线程安全。

    • JDK 1.8:虽然HashMap在JDK 1.8中仍然不是线程安全的,但由于其内部结构的优化和扩容策略的改变,它在并发场景下的性能得到了提升。

HashMap 的长度为什么是2的幂次方

可以用(length - 1)&hash这种位运算来代替%取余的操作进而提高性能。

为什么树化的临界值为8

当桶中结点个数为8时,出现的几率是亿分之6的,因此常见的情况是桶中个数小于8的情况,此时链表的查询性能和红黑树相差不多

ConcurrentHashMap 在JDK1.7 和JDK1.8 中差别

在 HashMap基础上增加了线程安全的设置

在JDK 1.7中,锁住整个Segment段

ConcurrentHashMap主要由Segment数组、HashEntry数组以及ReentrantLock组成。每个Segment都是一个ReentrantLock,可以锁住一段哈希表结构,从而实现分段锁。整个ConcurrentHashMap基于分段锁实现,提高了并发性能。然而,当HashEntry链表过大时,查询效率可能会降低。

而在JDK 1.8中,synchronized只锁定当前链表或者红黑树的首节点

ConcurrentHashMap进行了重大改进,摒弃了Segment,采用了synchronized+CAS+红黑树实现的数据结构。锁的粒度也从段锁缩小为结点锁,进一步提高了并发性能。此外,JDK 1.8还优化了put()方法的执行流程,只需要一次定位,并采用CAS+synchronized的机制进行加锁,降低了锁资源的争夺。当链表长度超过一定阈值时,链表会转换为红黑树,以提供更快的查找、插入和删除操作,从而解决了JDK 1.7中查询效率较低的问题

并发编程-高频面试

线程与进程的区别?

进程是资源分配的最小单位,它包含执行代码、系统资源和线程。线程是CPU调度的最小单位,共享进程资源,更轻量。进程间不共享内存,线程间共享内存空间。进程间通信需要进程间通信(IPC)机制,而线程间可以直接读写共享内存进行通信。

什么是线程的上下文切换?

线程的上下文切换是指CPU从一个线程切换到另一个线程时需要保存当前线程的状态(如程序计数器、栈指针等),并恢复下一个要执行线程的状态的过程。

Java中的线程有几种创建方式?

Java中创建线程主要有三种方式:

  • 继承Thread类并重写run()方法。

  • 实现Runnable接口并重写run()方法,然后将Runnable对象作为参数传递给Thread类的构造函数。

  • 实现Callable接口并使用FutureTask包装,通过线程池执行。

什么是线程的生命周期?

线程的生命周期通常包括新建(New)、就绪(Runnable)、阻塞(Blocked)、运行(Running)、终止&

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值