Java中的Hash值的计算方式,java哈希算法简单数据类型的具体实现

最近被提及Java中HashMap的一些实现及哈希冲突等,借鉴了一位老哥的部分解析,比较明白的展示hash算法的应用吧

结论:

  • 对于String、Integer等类复写了Object中的hashCode方法的类来说,有各自的实现方法
  • Object类中的hashCode()该方法是一个本地方法,Java将调用本地方法库对此方法的实现
    先上代码,
public class Test {
    public static void main(String[] args) {
        String str = "hello";
        String str2 = "world";
        String str3 = "a";
        String str4 = "1";
        Integer i = 1;
        System.out.println("hello的 hashcode = "+str.hashCode());
        System.out.println("world的 hashcode = "+str2.hashCode());
        System.out.println("a的 hashcode = "+str3.hashCode());
        System.out.println("字符串1的 hashcode = "+str4.hashCode());
        System.out.println("整数对象1的 hashcode = "+i.hashCode());
        String str5 = "abc";
        System.out.println("abc的 hashcode = "+str5.hashCode());
        String str6 = "abc ";
        System.out.println("abc 的 hashcode = "+str6.hashCode());
    }
}

代码的输出结果如下:

hello的 hashcode = 99162322
world的 hashcode = 113318802
a的 hashcode = 97
字符串1的 hashcode = 49
整数对象1的 hashcode = 1
abc的 hashcode = 96354
abc 的 hashcode = 2987006

​ 可以直观的看到,a字符的哈希值是97,是它的ASCII码值。然后整数对象的哈希值是它本身。经过查看源码,发现,hash值的计算,不同类型计算方式不同。具体实现如下:

Integer类的 hashcode() 方法在Integer类中被复写了,源码如下:

@Override
public int hashCode() {
    return Integer.hashCode(value);
}
public static int hashCode(int value) {
  	return value;
}

Integer类的hashcode返回的就是Integer本身的值。

对于String来说,具体的源码如下:

public int hashCode() {
    int h = hash;
    if (h == 0 && value.length > 0) {
        char val[] = value;

        for (int i = 0; i < value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

String对象会对对象的内容进行计算,得出hash值。

​ 对于字符来说,像字符a会被转换为对应的ACII码值,也就是97,由于char的位数少于int型的位数,所以31*h+val[i] 计算时会被强制转换为int值。

验证计算,

abc的hashcode值为96354,那么即为 31*(31*(31*0+97)+98)+99=96354

空格的ASCII码值为32,所以 "abc " hashcode 为 96354*31+32 = 2987006

对于上文举例的String和Integer来说是复写了hashCode方法,以上述方式计算了hash值。


另外:

散列函数的计算方法主要有:

  • 1、除余法

  • 2、乘余取整法

  • 3、平方取中法

  • 4、数字分析法

  • 5、基数转换法

  • 6、折叠法

冲突解决策略:

  • 1、分离链表法(拉链法)

    在每一个相同的散列地址上构建链表。

  • 2、闭散列方法(开放地址法)

### 回答1: 在Java,哈希表可能会经常出现哈希碰撞。哈希表是一种根据键(Key)来访问(Value)的数据结构,通过哈希函数将键映射到哈希表的索引位置上。由于哈希函数的映射结果可能不唯一,不同的键可能会被映射到同一个索引位置上,从而导致哈希碰撞。哈希碰撞会影响哈希表的性能,因此需要采取一些策略来减少哈希碰撞的发生,例如使用更好的哈希函数、调整哈希表的容量等。 ### 回答2: 在Java,哈希表(HashMap)在处理大量数据时可能会出现哈希碰撞。哈希碰撞是指不同的键(key)计算出的哈希hash value)相同的情况。由于哈希表使用哈希函数将键映射到数组索引,不同的键可能映射到相同的数组位置,这就导致了哈希碰撞的发生。 哈希碰撞的发生是无法避免的,因为哈希的范围是无限的,而存储空间是有限的。无论是哪种哈希函数,都无法将无限的哈希映射到有限的数组索引上,因此在开发过程,我们要考虑如何处理和解决哈希碰撞。 在JavaHashMap通过在发生哈希碰撞时使用链表(JDK8之前)或红黑树(JDK8及以后)来解决。当多个键映射到同一个数组索引上时,它们会组成一个链表或红黑树,使得查找、插入和删除键的操作仍然能够高效进行。 然而,当哈希表的数据量变得非常大,链表或红黑树的长度过长时,会降低哈希表的性能。为了尽量避免哈希碰撞,我们可以尝试选用更好的哈希函数、调整哈希表的负载因子(load factor)或使用其他类型的哈希表实现,如ConcurrentHashMap。 综上所述,在Java,哈希表(HashMap)会经常出现哈希碰撞。然而,Java提供了相应的解决方案,以提高哈希表的性能并降低哈希碰撞的影响。 ### 回答3: 在Java,哈希表(HashTable)实现了基于哈希函数的键对存储和查找机制。哈希碰撞是指不同的键对通过哈希函数计算后得到相同的哈希,从而导致它们被映射到哈希表相同的位置。 在Java的哈希表实现,哈希碰撞是可能发生的。这是因为哈希函数的计算过程无法避免某些键对具有相同的哈希。当不同的键对具有相同的哈希时,它们将被存储在哈希表的同一位置上。这会导致在查找键对时需要额外的操作来解决冲突,例如链表法或开放寻址法。 然而,哈希碰撞的概率通常较低,且可以通过几种方法来减少碰撞的发生。首先,选择一个好的哈希函数可以降低碰撞的概率。好的哈希函数应该能够将键对均匀地分布在哈希表,尽量避免相同哈希的出现。其次,哈希表的大小也会影响碰撞的概率,散列桶的数量越多,碰撞的可能性就越小。 在Java,除了传统的哈希表实现HashTable,还有更常用的HashMap实现,它采用了更高效的哈希算法(散列函数)和碰撞解决方法。HashMap使用链表法和红黑树结构来处理碰撞,以提高性能和减少碰撞的发生。 总的来说,在Java哈希表会经常出现哈希碰撞,但可以通过选择好的哈希函数和适当的哈希表大小来减少碰撞的概率,同时Java提供的高效哈希实现也能有效处理碰撞问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值