• Hashtable 相关面试集合(2022)


    在这里插入图片描述

    博主 默语带您 Go to New World.
    个人主页—— 默语 的博客👦🏻
    《java 面试题大全》
    🍩惟余辈才疏学浅,临摹之作或有不妥之处,还请读者海涵指正。☕🍭
    《MYSQL从入门到精通》数据库是开发者必会基础之一~
    🪁 吾期望此文有资助于尔,即使粗浅难及深广,亦备添少许微薄之助。苟未尽善尽美,敬请批评指正,以资改进。!💻⌨

    一级目录

    HashMap 和 Hashtable 的区别

    1. 线程是否安全: HashMap 是⾮线程安全的, HashTable 是线程安全的,因为 HashTable 内部的⽅法基本都经过 synchronized 修饰。(如果你要保证线程安全的话就使⽤ConcurrentHashMap 吧!);
    2. 效率: 因为线程安全的问题, HashMap 要⽐ HashTable 效率⾼⼀点。另外, HashTable基本被淘汰,不要在代码中使⽤它;
    3. 对 Null key 和 Null value 的⽀持: HashMap 可以存储 null 的 key 和 value,但 null 作为键只能有⼀个,null 作为值可以有多个;
      HashTable 不允许有 null 键和 null 值,否则会抛出NullPointerException 。(空指针异常)
    4. 初始容量⼤⼩和每次扩充容量⼤⼩的不同 :

    ① 创建时如果不指定容量初始值, Hashtable默认的初始⼤⼩为 11,之后每次扩充,容量变为原来的 2n+1。
    HashMap 默认的初始化⼤⼩为 16。之后每次扩充,容量变为原来的 2 倍。

    ② 创建时如果给定了容量初始值,那么Hashtable 会直接使⽤你给定的⼤⼩,⽽ HashMap 会将其扩充为 2 的幂次⽅⼤⼩( HashMap 中的 tableSizeFor() ⽅法保证,下⾯给出了源代码)。也就是说 HashMap 总是使⽤ 2 的幂作为哈希表的⼤⼩,后⾯会介绍到为什么是 2 的幂次⽅。
    5. 底层数据结构: JDK1.8 以后的 HashMap 在解决哈希冲突时有了较⼤的变化,当链表⻓度⼤于阈值(默认为 8)(将链表转换成红⿊树前会判断,如果当前数组的⻓度⼩于 64,那么会选择先进⾏数组扩容,⽽不是转换为红⿊树) 时,将链表转化为红⿊树,以减少搜索时间。Hashtable 没有这样的机制

    HashMap 和 HashSet区别

    如果你看过 HashSet 源码的话就应该知道:HashSet 底层就是基于 HashMap 实现的。
    ( HashSet 的源码⾮常⾮常少,因为除了 clone() 、 writeObject() 、 readObject() 是 HashSet
    ⾃⼰不得不实现之外,其他⽅法都是直接调⽤ HashMap 中的⽅法

    HashSet如何检查重复

    以下内容摘⾃我的 Java 启蒙书《Head fist java》第⼆版:
    当你把对象加⼊ HashSet 时, HashSet 会先计算对象的 hashcode 值来判断对象加⼊的位置,同时也会与其他加⼊的对象的 hashcode 值作对比,如果没有相符的 hashcode , HashSet 会假设对象没有重复出现。但是如果发现有相同 hashcode 值的对象,这时会调⽤ equals() ⽅法来检查hashcode 相等的对象是否真的相同。如果两者相同, HashSet 就不会让加⼊操作成功.

    Jdk1.7到Jdk1.8 HashMap 发⽣了什么变化(底层)?

    1. 1.7中底层是数组+链表,1.8中底层是数组+链表+红⿊树,加红⿊树的⽬的是提⾼HashMap插⼊和 查询整体效率
    2. 1.7中链表插⼊使⽤的是头插法,1.8中链表插⼊使⽤的是尾插法,因为1.8中插⼊key和value时需要 判断链表元素个数,所以需要遍历链表统计链表元素个数,所以正好就直接使⽤尾插法
    3. 1.7中哈希算法⽐较复杂,存在各种右移与异或运算,1.8中进⾏了简化,因为复杂的哈希算法的⽬的 就是提⾼散列性,来提供HashMap的整体效率,⽽1.8中新增了红⿊树,所以可以适当的简化哈希 算法,节省CPU资源

    ConcurrentHashMap 和 Hashtable 的区别

    ConcurrentHashMap 和 Hashtable 的区别主要体现在实现线程安全的⽅式上不同。
    底层数据结构: JDK1.7 的 ConcurrentHashMap 底层采⽤ 分段的数组+链表 实现,JDK1.8采⽤的数据结构跟 HashMap1.8 的结构⼀样,数组+链表/红⿊⼆叉树。 Hashtable 和JDK1.8 之前的 HashMap 的底层数据结构类似都是采⽤ 数组+链表 的形式,数组是HashMap 的主体,链表则是主要为了解决哈希冲突⽽存在的;

    实现线程安全的⽅式(重要): ① 在 JDK1.7 的时候, ConcurrentHashMap (分段锁)对整个桶数组进⾏了分割分段( Segment ),每⼀把锁只锁容器其中⼀部分数据,多线程访问容器⾥不同数据段的数据,就不会存在锁竞争,提⾼并发访问率。 到了 JDK1.8 的时候已经摒弃了 Segment 的概念,⽽是直接⽤ Node 数组+链表+红⿊树的数据结构来实现,并发控制使⽤ synchronized 和 CAS 来操作。(JDK1.6 以后 对 synchronized 锁做了很多优化) 整个看起来就像是优化过且线程安全的 HashMap ,虽然在 JDK1.8 中还能看到Segment 的数据结构,但是已经简化了属性,只是为了兼容旧版本;② Hashtable (同⼀把锁) :使⽤ synchronized 来保证线程安全,效率⾮常低下。当⼀个线程访问同步⽅法时,其他线程也访问同步⽅法,可能会进⼊阻塞或轮询状态,如使⽤ put 添加元素,另⼀个线程不能使⽤ put 添加元素,也不能使⽤ get,竞争会越来越激烈效率越低.

    如对本文内容有任何疑问、建议或意见,请联系作者,作者将尽力回复并改进📓;(联系微信:Solitudemind )

  • 相关阅读:
    Spring Boot事件机制浅析
    Angular:升级Angular 13到Angular 14
    zoj 1465 Wall
    springboot整合neo4j--采用Neo4jClient和Neo4jTemplate方式
    go语言GoFrame+Vue+ElementUI后台管理搭建教程
    [WSL][ubuntu]解决WSL Ubuntu+xfce4 图形界面一段时间后黑屏
    Driver8833电机驱动模块的使用(STM32为主控)
    【ArcGIS微课1000例】0049:制图表达(4)---自由式制图表达
    系统集成|第二十章(笔记)
    【PointNet—论文笔记分享】
  • 原文地址:https://blog.csdn.net/qq_42055933/article/details/126594719