为啥 ByteBuffers hashCodes 是一样的?

Posted

技术标签:

【中文标题】为啥 ByteBuffers hashCodes 是一样的?【英文标题】:why are ByteBuffers hashCodes the same?为什么 ByteBuffers hashCodes 是一样的? 【发布时间】:2012-06-18 19:42:13 【问题描述】:

我有一个这样的类构造函数:

public JavoImageCorrectedDataHeader()
    
        ByteBuffer buffer = ByteBuffer.allocate(this.size());
        buffer.order(java.nio.ByteOrder.LITTLE_ENDIAN);
        setByteBuffer(buffer, 0);
        System.out.println("buffer.hasCode=" + buffer.hashCode());
    

在我的其他课程中,我使用

在不同的位置和时间创建了上述课程的许多实例
new JavoImageCorrectedDataHeader()

然后,我希望它会为他们打印出不同的 hashCode。但我实际上看到打印出相同的 hashCode

buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241
buffer.hasCode=1742602241

我必须错过一些关于如何使用 ByteBuffer 的内容。

【问题讨论】:

docs.oracle.com/javase/1.4.2/docs/api/java/nio/… - ByteBuffer.hashCode 取决于缓冲区中的剩余内容。 即使两个对象具有相同的hashCode,这并不意味着它们的相似性或相等性。 @Erik 请不要参考旧文档,而是参考 Java 6 或 7。这是ByteBuffer 的实际文档 【参考方案1】:

来自 javadoc:

字节缓冲区的哈希码仅取决于其剩余元素;也就是说,在从 position() 到且包括在 limit() - 1 处的元素上。

因为缓冲区哈希码是依赖于内容的,所以不建议在哈希映射或类似数据结构中使用缓冲区作为键,除非知道它们的内容不会改变。

如果您没有填充ByteBuffers,或者使用相同的东西填充它们,哈希码将是相同的。

【讨论】:

【参考方案2】:

来自ByteBuffer.java源代码:

public int hashCode () 
    int hashCode = get(position()) + 31;
    int multiplier = 1;
    for (int i = position() + 1; i < limit(); ++i) 
        multiplier *= 31;
        hashCode += (get(i) + 30)*multiplier;
    
    return hashCode;

在您当前的实现下,position() 始终返回 0,因此哈希码始终相同。哈希码取决于缓冲区的内容,而不是用于表示它的物理对象。

【讨论】:

【参考方案3】:

这是正确的行为。根据 ByteBuffer 文档:

当且仅当,两个字节缓冲区相等

它们具有相同的元素类型,

它们具有相同数量的剩余元素,并且

剩余元素的两个序列,独立于它们的起始位置,逐点相等。

字节缓冲区不等于任何其他类型的对象。

所以,假设 this.size() 总是返回相同的东西,你的缓冲区总是相等的。根据 hashCode 的通用合约,它们必须具有相同的哈希码。

您似乎正在尝试使用 hashCode 来确定对象身份 - 这不是一个好主意(因为 hashCode 和 == 如何交互)。如果您需要将类的实例彼此区分开来,并且需要比 == 运算符提供的更多内容,则必须找到其他方法来做到这一点。

【讨论】:

【参考方案4】:

ByteBuffer.hashcode 让您计算包装字节[] 的哈希值。在这种情况下,新初始化的 byte[] 的内容对于每个字节都是 0。假设 ByteBuffer 内容相同,hashcode 相同。

【讨论】:

以上是关于为啥 ByteBuffers hashCodes 是一样的?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 hashCode 中使用素数?

为啥在 hashCode 中使用素数?

由于 Netty 中的 ByteBuffers 导致的内存泄漏

多线程 ByteBuffers 比顺序慢?

JAVA中重写equals方法为啥要重写hashcode方法说明

【彻底理解】 为啥重写equals()方法为啥要重写hashCode()方法