当前位置: 首页 > 知识库问答 >
问题:

string - java中字符串的hashcode算法原理和冲突概率?

子车高歌
2023-04-21

问题铺垫

hotspot jdk1.8:

    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = value.length;
            if (n == anotherString.value.length) {
                char v1[] = value;
                char v2[] = anotherString.value;
                int i = 0;
                while (n-- != 0) {
                    if (v1[i] != v2[i])
                        return false;
                    i++;
                }
                return true;
            }
        }
        return false;
    }
    /**
     * Returns a hash code for this string. The hash code for a
     * {@code String} object is computed as
     * <blockquote><pre>
     * s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
     * </pre></blockquote>
     * using {@code int} arithmetic, where {@code s[i]} is the
     * <i>i</i>th character of the string, {@code n} is the length of
     * the string, and {@code ^} indicates exponentiation.
     * (The hash value of the empty string is zero.)
     *
     * @return  a hash code value for this object.
     */
    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;
    }

tips:

h = 31 * h + val[i]; 这里的实际上是整形和字符相加,也就是和字符的对应的 unicode 编码码值或者保留值(高代理区和低代理区)相加(范围即 0-65535,这里可能与是否超过 BMP 无关(代理区模式))


hashcode和equals满足如下条件:

1. equals() 相等的两个对象他们的 hashCode() 肯定相等
2. equals() 不相等的两个对象, hashcode() 有可能相等
3. hashCode() 相等的两个对象他们的 equals() 不一定相等
4. hashcode() 不等,一定能推出 equals() 也不等

我们知道,String 类对 hashcode 和 equals 进行了覆写,相同字符串的值的 equals() 才会相等,当然此时 hashcode 也是相等的 (这里满足了1).
不同字符串值的 hashcode 也可能相等 ( hash 冲突)(这里符合2).


问题

我想问的是 (这也许是个数学问题):

  1. 条件3冲突的概率? s[0]31^(n-1) + s[1]31^(n-2) + ... + s[n-1]
  2. 如何证明String类符合4?

共有1个答案

公冶翰池
2023-04-21

1、字符串的长度虽然有理论的最大值,但是在这个问题里可以按无限来算,而且你没给定源字符串的范围,在此基础上,可以认为hashCode为1~Integer.INT_MAX之间任意的值都有可能。相等的概率自然是1/Integer.INT_MAX。考虑到具体情况,如果输入字符串里有大量的短串,比如"abc" "ac" "mmm"之类,哈希码可能会集中在一个范围。
2、把字符串看作数列A,另外定义一个数列B:
规定B(1) = 31 * A(1)
对于任意大于1的正整数n,B(n) = 31 * B(n-1) + A(n)
用数学归纳法就能知道,A只能得到唯一的B(n)。

 类似资料:
  • COBOL中的字符串处理语句用于对字符串执行多个功能操作。 以下是字符串处理语句 - Inspect String Unstring Inspect Inspect verb用于计算或替换字符串中的字符。 可以对字母数字,数字或字母值执行字符串操作。 检查操作从左到右执行。 用于字符串操作的选项如下 - Tallying Tallying选项用于计算字符串字符。 Syntax 以下是Tallyin

  • 问题内容: Java字符串的hashCode值计算为(): 是否在任何情况下(例如JVM版本,供应商等),以下表达式将被评估为false? 更新#1:如果您声称答案是“是的,则有这种情况”-然后请举一个具体示例说明何时“这是Java字符串”。。请尽量具体/具体尽可能。 更新#2:我们都知道,依赖hashCode()的实现细节通常是不好的。但是,我在专门谈论String.hashCode()-因此请

  • 问题内容: 我是学习Java的C ++人。我在读《有效的Java》,使我有些困惑。它说永远不要写这样的代码: 因为它创建了不必要的String对象。但是应该这样写: 到目前为止还可以…但是,考虑到此类: 为什么第一个陈述可以?不是吗 我如何使行为像这样,使上面的语句可以正常运行(带有和不带有)?字符串到底有什么用,它能够像这样传递文字就可以了吗?据我了解,Java中没有“复制构造函数”的概念吗?

  • 本文向大家介绍Java数字和字符串拼接原理及案例,包括了Java数字和字符串拼接原理及案例的使用技巧和注意事项,需要的朋友参考一下 字符串拼接是我们在Java代码中比较经常要做的事情,就是把多个字符串拼接到一起。都知道,String 是 Java 中一个不可变的类,所以一旦被实例化就无法被修改。 注意细节 字符是char 类型,字符串是String 类型 1、数字拼接char,得到的还是数字,相当

  • 问题内容: 几分钟前,我看到了这个问题,并决定查看java String类,以检查运算符是否有一些重载。 我什么也找不到,但我知道我可以做到 在哪里实施? 问题答案: 从精细手册中: Java语言为字符串连接运算符(+)以及将其他对象转换为字符串提供了特殊支持。字符串连接是通过(或)类及其方法实现的。字符串转换是通过toString方法实现的,该方法由Object定义并由Java中的所有类继承。有

  • 本文向大家介绍Java中的字符串缓冲区和字符串生成器之间的区别,包括了Java中的字符串缓冲区和字符串生成器之间的区别的使用技巧和注意事项,需要的朋友参考一下 字符串缓冲区和StringBuilder都是可变类,可用于对字符串对象执行操作,例如字符串的反向,压缩字符串等。我们可以在不创建字符串新对象的情况下修改字符串。字符串缓冲区是线程安全的,而字符串生成器不是线程安全的。因此,它比字符串缓冲区快