A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

Hash相关知识点
面试基本提纲
1. hash 表是什么
2. hash 表用来做什么
3. hash 表是怎么做到可以搜索的?
    1. hash 值如何求,hashCode 是什么,用来做什么
    2. 冲突
         1. 什么是冲突
         2. 怎么避免冲突
         3. 冲突了怎么办
    3. equals 方法用来做什么
4. hash 表用在 Java 中是什么形式的
    1. HashMap 是什么
    2. HashSet 是什么
    3. HashMap 中为什么用红黑树
5. hash 表是线程安全的么?
答题技巧
既然是位于数据结构,那么首先要分析它的具体结构(特征),具体的实现形式就如HashMap

核心知识点
首先介绍hash是为了把任意长度的输入,通过散列算法变换成固定长度的输出,可以拆分成数组+链表的形式,然后进行hash冲突,当size大于等于容量*加载因子(0.75),就会发生扩容,在多线程中会不安全,特别注意的是jdk1.7使用头插法,jdk1.8使用尾插法。

Ⅰ、Hash
1.hash表是什么
&&2.hash 表用来做什么
hash意思是散列,是把任意长度的输入,通过散列算法变换成固定长度的输出;

通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。

3.hash 表是怎么做到可以搜索的?
1. hash 值如何求,hashCode 是什么,用来做什么

通过hash算法,hashCode() 的作用是获取哈希码,也称为散列码;它实际上是返回一个int整数。这个哈希码的作用是确定该对象在哈希表中的索引位置(粗略理解为就是在hash表中对应的位置)。

hashCode的存在主要是为了查找的快捷性,hashCode是用来在散列存储结构中确定对象的存储地址,先通过hashCode 比较在通过equals比较,例如插入第1001个数据时,需要依次和前1000个比,如果用hashCode,可将前面数据的范围缩小(不同对象的hashCode可能相等),这样如果hashCode如果不同,直接false,相同时调用equals方法进一步确认。

2. 冲突

         1. 什么是冲突

         2. 怎么避免冲突

         3. 冲突了怎么办

hash冲突(其实就是问为什么引入hash这个概念,压缩映射,hash意思是散列,是把任意长度的输入,通过散列算法变换成固定长度的输出),Java中,当size大于等于容量*加载因子(0.75),就会发生扩容,举个例子比如容量16,size就是12



  3. equals 方法用来做什么——equals方法和hashCode的关系

equals()方法:(离散数学中的知识“等价”)

• 对称性:如果x.equals(y)返回是“true”,那么y.equals(x)也应该返回是“true”。

• 反射性:x.equals(x)必须返回是“true”。

• 类推性:如果x.equals(y)返回是“true”,而且y.equals(z)返回是“true”,那么z.equals(x)也应该返回是“true”。

• 一致性:如果x.equals(y)返回是“true”,只要x和y内容一直不变,不管你重复x.equals(y)多少次,返回都是“true”。

推论关系:

equals()相等的两个对象,hashCode()一定相等;

反过来:hashCode()不等,一定能推出equals()也不等;

hashCode()相等,equals()可能相等,也可能不等

这里延伸出一个知识点如何覆写equals方法(),忘记了……见最后的代码



Ⅱ、HashMap
4.hash 表用在 Java 中是什么形式的
    1. HashMap 是什么

    2. HashSet 是什么

    3. HashMap 中为什么用红黑树

hash意思是散列,是把任意长度的输入,通过散列算法变换成固定长度的输出;HashMap实现的原理是:数组+链表(jdk1.7)

数组+链表+红黑树(8个根据泊松分布,6个降为链表)jdk1.8

HashMap的size大于等于(容量*加载因子)的时候,会触发扩容的操作

HashSet底层通过包装HashMap来实现,HashSet在添加一个值的时候,实际上是将此值作为HashMap中的key来进行保存

5.hash 表是线程安全的么?
HashMap在多线程下不安全

HashMap默认的容量是16,随着元素不断添加到HashMap里,出现hash冲突的机率就更高,那每个桶对应的链表就会更长, 环形链接出现,逆置链表等问题,问题出现在transefer()方法中,(resize()这个大的方法中),jdk1.8改进:使用尾插法

HashTable不允许空值和空键,synchronized关键字实现线程安全

HashTable锁分离技术,每个段其实就是一个小的HashTable,它们有自己的锁。只要多个修改操作发生在不同的段上,它们就可以并发进行。

附录:代码(应该有hashCode的,我这里节省空间,那么问题来了为什么重写equals方法还要重写hashCode)
class People{
        String name;
        @Override
        public boolean equals(Object obj) {
     //比较对象相等
                if (this == obj)
                        return true;
   //对象为空
                if (obj == null)
                        return false;
   //反射?instanceof 也可以,在相同的一个大类里
                if (getClass() != obj.getClass())
                        return false;
   //强制类型转换
                People other = (People) obj;
                if (name == null) {
                        if (other.name != null)
                                return false;
                } else if (!name.equals(other.name))
                        return false;
                return true;
        }
}
后记
扩展知识
HashMap 的长度为什么是2的幂次

hash%length==hash&(length-1)

迁移
Object类有哪些方法?

11个方法,getClass()

hashCode() clone() toString() notify() notifyAll() wait() finalize()等


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马