【问题标题】:Why does changing StringBuilder change its hashCode?为什么更改 StringBuilder 会更改其 hashCode?
【发布时间】:2020-12-09 14:22:44
【问题描述】:

这是输入。

    public static void main(String[] args){

        StringBuilder builder = new StringBuilder("hello");
        printBuilder(builder);

        // append
        builder.append(" everyone");
        printBuilder(builder);

        builder.append(", what's up?");
        printBuilder(builder);
    }

    private static void printBuilder(StringBuilder dataBuild){
    StringBuilder build = new StringBuilder(dataBuild);
    System.out.println("data = " + build);
    System.out.println("length = " + build.length());
    System.out.println("capacity = " + build.capacity());
    int addressBuild = System.identityHashCode(build);
    System.out.println("address = " + Integer.toHexString(addressBuild);
    }

这是输出。

  • 数据 = 你好
  • 长度 = 25
  • 容量 = 21
  • 地址 = 5b480cf9
  • 数据 = 大家好
  • 长度 = 14
  • 容量 = 30
  • 地址 = 6f496d9f
  • data = 大家好,最近怎么样?
  • 长度 = 26
  • 容量 = 42
  • 地址 = 723279cf

为什么地址与其他地址不同? 我虽然会是一样的。我尝试了不同的方法,如插入、替换、charAt,但地址仍然不同。谁能告诉我为什么?

【问题讨论】:

  • 是的。哈希码更改的原因是您每次调用它时都会在printBuilder 中显式创建一个新的StringBuilder。仔细查看您的代码。
  • 一个澄清:hashCode 不是一个对象的地址。默认实现(如果类没有覆盖方法)可能基于地址或其他因素,但仅此而已。
  • 我还是一样你能解释一下你为什么这么认为吗?

标签: java stringbuilder hashcode


【解决方案1】:

printBuild() 中,每次调用都会生成一个新的StringBuilder。每次都会为新构建器打印哈希:

int addressBuild = System.identityHashCode(build);

你不能合理地期待不同的结果。如果您想每次都看到相同的哈希,请删除以下行:

StringBuilder build = new StringBuilder(dataBuild);

直接对输入参数dataBuild进行操作:它作为引用传入。

详细说明:System.identityHashCode 产生的结果只有在对象相同时才能保证相同(如==,而不是equals())。当然,与任何散列一样,两个不相等的对象可能具有相同的散列,但该函数确实会尝试减少重叠。正如预期的那样,结果通常基于内存位置,尽管它通常不是内存位置本身。

【讨论】:

    【解决方案2】:

    System#identityHashCode 不返回对象的地址。

    为给定对象返回与返回相同的哈希码 通过默认方法 hashCode(),无论给定对象的 类覆盖 hashCode()。空引用的哈希码是 零。

    类的每个对象都有不同的哈希码。由于每次调用 printBuilder 都会创建一个新对象,因此您会得到不同的哈希码。

    注意:使用== 的比较对于具有相同哈希码的引用返回true

    class Main {
        public static void main(String[] args) {
            Boolean b1 = true;
            Boolean b2 = Boolean.valueOf("true");
            System.out.println(System.identityHashCode(b1));
            System.out.println(System.identityHashCode(b2));
            System.out.println(b1 == b2);
    
            String s1 = "Hello";
            String s2 = s1;
            String s3 = new String("Hello");// Creates a new object and hence s3 will have a different hash code
            System.out.println(System.identityHashCode(s1));
            System.out.println(System.identityHashCode(s2));
            System.out.println(s1 == s2);
            System.out.println(System.identityHashCode(s3));
            System.out.println(s2 == s3);
        }
    }
    

    输出:

    992136656
    992136656
    true
    511833308
    511833308
    true
    1297685781
    false
    

    【讨论】:

    • 地址与否无关紧要:重要的是 OP 每次都在创建一个新对象
    • @MadPhysicist - 我在哪里说过这是一个地址?
    • 你说不是,暗示这与问题有关。
    • @MadPhysicist - 我坚持我的声明,System#identityHashCode does not return the address of the object.
    • 我一点也不反对你。它真的并且真的没有返回地址。但是,一个好的答案的要求是它是真实的并能解决问题。在我看来,你的帖子只满足前者。
    猜你喜欢
    • 2023-03-29
    • 2014-03-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    相关资源
    最近更新 更多