首页 > 编程语言 >JAVA面试题:HashMap和HashTable的区别

JAVA面试题:HashMap和HashTable的区别

时间:2024-07-23 13:53:40浏览次数:18  
标签:面试题 JAVA HashMap 哈希 链表 key hash null

一、先说结论

        HashMapHashTable 都是 Map 接口的实现类。HashMap 采用数组、链表和红黑树的数据结构,非线性安全且无序,查找效率高,初始化默认容量为 2^4,每次扩容为原来的 2 倍;而 HashTable 采用数组和链表的数据结构,线性安全,键值均不允许为 null,默认初始大小为 11,每次扩充为原来的 2n+1。

二、什么是Hash(哈希)?

哈希(Hash)是一种通过特定算法将输入数据转换为固定长度的输出数据的过程。这个固定长度的输出数据称为哈希值或哈希码。哈希算法的主要特征包括:

  1. 固定长度输出:无论输入数据的大小或长度,哈希函数总是生成固定长度的哈希值。例如,SHA-256 哈希函数总是生成 256 位长的哈希值。

  2. 唯一性:理想情况下,哈希函数对不同的输入应该产生不同的哈希值,即低碰撞性。尽管存在哈希碰撞(不同的输入产生相同的哈希值),好的哈希算法尽量减少碰撞的发生。

  3. 不可逆性:从哈希值不能反推出原始输入数据。哈希函数是单向的,这意味着你不能通过哈希值轻易地得到原始数据。

  4. 高效性:哈希函数的计算应该足够快,即使对于大的数据集也应高效。

哈希在计算机科学和信息技术中有广泛的应用,例如:

  • 数据检索:在数据结构中,如哈希表,用于快速查找、插入和删除操作。
  • 数据完整性:在文件传输中,使用哈希值来验证数据的完整性。
  • 密码学:用于生成加密哈希,用于密码存储、数字签名等。

HashMapHashTable 都是基于哈希(Hash)原理的 Map 接口实现类,它们利用哈希函数将键(Key)映射到表中的位置,从而实现快速的查找、插入和删除操作。 

三、HashMap

HashMap 是 Java 集合框架中的一个重要实现类,广泛用于存储键值对。利用哈希函数、高效的冲突处理机制和动态扩容来实现快速的数据存储和查找,是 Java 中最常用的键值存储结构之一。

HashMap 的数据结构

  • 数组: HashMap 的底层是一个数组,每个数组元素称为一个桶(bucket)。
  • 链表: 当多个键的哈希值相同时,这些键会被存储在同一个桶中,形成一个链表。
  • 红黑树: 当某个桶中的链表长度超过一定阈值(默认是8)时,链表将被转换为红黑树,以提高查找效率。

HashMap 的哈希实现

1. 哈希函数
  • HashMap 使用键的 hashCode 方法计算哈希码,然后通过扰动函数(perturbation function)进一步混合哈希码的高位和低位,以减少冲突。
    static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }
    

    这段代码将键的 hashCode 值与其高16位进行异或运算,以混合哈希码的高低位。

    2. 确定桶的位置
  • HashMap 使用 (n - 1) & hash 来确定键值对在哈希表中的位置,其中 n 是数组的长度。
int index = (n - 1) & hash;
3. 处理冲突
  • 初始时,HashMap 采用链表来处理冲突。当数组长度已经扩容到64且该桶中的链表长度超过8时,该链表会转换为红黑树(当长度低于6时变回链表)
Node<K,V> e;
if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
    e = p;
else if (p instanceof TreeNode)
    e = ((TreeNode<K,V>)p).getTreeNode(hash, key);
else {
    for (int binCount = 0; ; ++binCount) {
        if ((e = p.next) == null) {
            p.next = newNode(hash, key, value, null);
            if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                treeifyBin(tab, hash);
            break;
        }
        if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
            break;
        p = e;
    }
}
4. 扩容机制
  • HashMap 中的元素个数超过容量和负载因子(默认为0.75)的乘积时,HashMap 会进行扩容,新的容量是旧容量的两倍。
void resize() {
    Node<K,V>[] oldTable = table;
    int oldCap = oldTable.length;
    int newCap = oldCap << 1;
    Node<K,V>[] newTable = (Node<K,V>[])new Node[newCap];
    transfer(newTable);
}
5. HashMap 的特性
  • 非线程安全: HashMap 是非线程安全的,在多线程环境下使用时需要通过外部同步机制保证线程安全。
  • 无序: HashMap 中的键值对是无序的,存储顺序不保证与插入顺序一致。
  • 允许 null: HashMap 允许一个 null 键和多个 null 值。

四、HashTable

Hashtable 是 Java 集合框架中的一个重要 Map 实现类,用于存储键值对。它提供线程安全的键值存储功能,具有同步机制,并且不允许 null 键或值。

Hashtable 的数据结构

  • 数组: Hashtable 的底层也是一个数组,用于存储键值对。
  • 链表: 当多个键的哈希值相同时,这些键值对会被存储在同一个桶中,形成一个链表。

Hashtable 的哈希实现

1. 哈希函数
  • Hashtable 使用键的 hashCode 方法计算哈希码,然后通过对数组长度取模的方式确定在哈希表中的位置。
int index = (hash & 0x7FFFFFFF) % table.length;

这里的哈希码通过与 0x7FFFFFFF 进行与操作,确保哈希码为非负值,然后对表的长度取模,以确定桶的位置。

2. 处理冲突
  • Hashtable 使用链表来处理冲突。当多个键的哈希值相同时,它们会被存储在同一个桶中,通过链表链接。
3. Hashtable 的特性
  • 线程安全: Hashtable 是线程安全的,大多数方法都是同步的。这使得它在多线程环境下安全,但也可能因为同步开销而影响性能。
  • 不允许 null 键或值: 与 HashMap 不同,Hashtable 不允许键或值为 null。如果尝试插入 null 键或值,将抛出 NullPointerException
  • 初始容量和扩容: 默认的初始容量为 11,每次扩容时,容量变为原来的 2n+1。

 

标签:面试题,JAVA,HashMap,哈希,链表,key,hash,null
From: https://blog.csdn.net/weixin_58856455/article/details/140633600

相关文章

  • 【Java常用设计模式】通俗易懂的玩转单例、建造者、工厂、策略模式(保姆篇)
    文章目录单例模式建造者模式工厂模式策略模式本篇小结更多相关内容可查看在一个狂风骤雨的下午,有人突然问了我一句,单例模式是什么,我愣了,相信看完这篇就不会愣了,本文以通俗易懂的方式写的,可能有不严谨的地方......
  • 计算机课程设计:JavaWeb期刊管理系统
    计算机课程设计:JavaWeb期刊管理系统项目说明 使用JavaWeb开发的数据库显示界面的课程设计,支持数据分页查询以及期刊的模糊搜索,首页采用动态二维码生成进行校验,支持上传图片,用户密码采用md5加密,支持期刊的分页显示。使用方法:这里说明一下:大致的使用方法1、getclone......
  • java学习day01
    一.java安装1.1安装java1.81.2java内创建文件夹jdk和jre分别安装java的jdk和jre1.3环境变量JAVA_HOMEE:\work\java\jdk(自己电脑的文件位置)CLASSPATH.;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;Path内增加%JAVA_HOME%\bin(上移到最上方)二.java2.1......
  • java学习day02
    一.数据类型1.1本质数据存储形式,存储空间大小1.2存储整数存储:1.3分类基本数据类型数值型整型byte字节8bit-128~127short短整型16bit-32768~32767int整型32bit-2,147,483,648~2,147,483,647long长整型64bit浮点型float单浮点32bitdouble双浮......
  • 三种语言实现快速选择(C++/Python/Java)
    题目给定一个长度为......
  • 【前端】JavaScript入门及实战91-95
    文章目录91DOM92事件93文档的加载94DOM查询(1)95图片切换的练习91DOM<!DOCTYPEhtml><html><head><title></title><metacharset="utf-8"><style></style></head><body> <buttonid="btn&quo......
  • 【前端】JavaScript入门及实战86-90
    文章目录86正则表达式87字符串和正则相关的方法88正则表达式语法(1)89正则表达式语法(2)90邮件的正则86正则表达式<!DOCTYPEhtml><html><head><title></title><metacharset="utf-8"><scripttype="text/javascript"> /* 使用字面量来创建正......
  • 【前端】JavaScript入门及实战96-100
    文章目录96DOM查询(2)97DOM查询(3)98全选练习(1)99全选练习(2)100全选练习(3)96DOM查询(2)<!DOCTYPEhtml><html><head><title></title><metacharset="utf-8"> <scripttype="text/javascript"> window.onload=......
  • Redis常见面试题汇总
    1.Redis中的底层数据结构String(字符串、整数或浮点数):String是Redis最基本的数据类型,一个key对应一个value,value的最大值为512MString类型是二进制安全的(原理在2),意味着redis可以包含任何数据,如图片、视频(可以转换为二进制编码)和序列化对象List(列表):redis列表是简单的字符......
  • IDEA解决java注释顶格、xml注释右对齐+无空格问题
    先配置java中注释格式: 然后是配置xml中的注释格式:还是CodeStyle,从java往下滑动到xml......