【问题标题】:Can a StringBuffer be used as a key in a HashMap?StringBuffer 可以用作 HashMap 中的键吗?
【发布时间】:2015-09-14 09:37:36
【问题描述】:

StringBuffer 可以作为 HashMap 中的键吗?
如果是这样,使用 String 和 StringBuffer 作为 key 有什么区别?

【问题讨论】:

  • 您指的是什么语言或库?你应该用它来标记你的问题。
  • @jB 语言是java

标签: java hashmap


【解决方案1】:

StringBuffer 可以作为 HashMap 中的键吗?

不,因为StringBuffer 既不覆盖equals 也不覆盖hashCode,所以它不适合作为HashMap 键(回想一下HashMap 依赖于这两种方法来判断给定的键是否存在于地图)。

除此之外,StringBuffers 是可变的,您通常希望 Map 键是不可变的。来自Map

注意:如果将可变对象用作映射键,则必须非常小心。如果对象的值以影响equals 比较的方式更改,而对象是映射中的键,则不指定映射的行为。此禁令的一个特殊情况是不允许映射包含自己作为键。虽然允许映射将自身作为值包含在内,但建议格外小心:equalshashCode 方法在此类映射上不再明确定义。

【讨论】:

    【解决方案2】:

    不,你不能,除非你想区分单独的缓冲区而不是它们的内容。 StringBuffer 类没有实现 equalshashCode,这意味着它从 Object 继承了这些方法。这些方法的Object 实现只区分对象实例,而不区分它们的内容。

    换句话说,如果您有两个具有相同内容的StringBuffer 实例,则它们不会被视为相等。更奇怪的是,如果你用不同的值重新插入同一个缓冲区,它被认为等于前一个。


    一般来说,您应该小心使用可变值作为键。突变不会改变Map 中的位置,因为Map 实例不会收到更改通知。在这种情况下,由于equals无论如何都没有实现,所以不会出现这个问题。

    【讨论】:

      【解决方案3】:

      java 中的所有类都旨在用作哈希键,因为它们都继承了超方法hashCode。尽管在某些情况下,尽管它可能编译得很好,但会很奇怪,例如 Connection 或 Streams... 或 StringBuffer。这就是为什么:

      StringStringBuffer 之间的主要区别在于,String 在设计上是不可变,它包含hashCode 的正确实现。相反,StringBuffers 可能会更改,因此,此类没有正确实现 hashCode:它不会覆盖从 Object 继承的默认实现。现在你可以看到后果了:StringBuffer 不能包含高质量的哈希,也不能与其内容保持一致,从而破坏了哈希算法的结果。

      【讨论】:

        【解决方案4】:

        是的,任何对象都可以用作HashMap 中的键,尽管这可能不是一个好主意。

        类 HashMap

        Type Parameters:
            K - the type of keys maintained by this map
            V - the type of mapped values
        

        来自this SO answer

        当您将键值对放入映射时,哈希映射将查看 密钥的哈希码,并将该对存储在其中的桶中 标识符是密钥的哈希码。 (...) 看上面 机制,您还可以看到需要什么要求 hashCode()equals() 方法的键(...)

        但是请注意,StringBuffer 不会覆盖所需的方法,因此您的“键”将是对象的内存地址。来自the hashcode() docs

        (这通常通过转换内部地址来实现 对象转换成整数,但这种实现技术不是 JavaTM 编程语言所要求的。)

        意味着它用作密钥将与 String 的非常不同:

        Map<String, String> hashA = new HashMap<>();
        a.put('a', 'a');
        System.out.println(hashA.get('a')); //prints 'a'
        
        Map<StringBuffer, String> hashB = new HashMap<>();
        StringBuffer buffer = new StringBuffer('a');
        hashB.put(buffer, 'a');
        System.out.println(hashB.get(new StringBuffer('a'))); //prints null
        System.out.println(hashB.get(buffer)); //prints 'a'
        

        【讨论】:

          猜你喜欢
          • 2014-07-10
          • 1970-01-01
          • 2013-05-26
          • 2014-06-16
          • 1970-01-01
          • 2015-03-05
          • 2020-03-30
          • 2014-07-14
          相关资源
          最近更新 更多