6

I have a class constructor like this:

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());
    }

In my other classes, I create many instances of above class in different locations and time by using

new JavoImageCorrectedDataHeader()

Then, I expected it will print out different hashCode for them. but I actually see the same hashCode is print out:

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

I must miss something about how to use the ByteBuffer.

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
5YrsLaterDBA
  • 33,370
  • 43
  • 136
  • 210
  • http://docs.oracle.com/javase/1.4.2/docs/api/java/nio/ByteBuffer.html#hashCode() - `ByteBuffer.hashCode` is dependent on remaining content in the buffer. – Erik Jun 18 '12 at 19:47
  • Even if two objects have the same `hashCode`, that implies nothing about their similarity or equality. – Greg Hewgill Jun 18 '12 at 19:49
  • @Erik please don't refer to old documentation, instead Java 6 or 7. This is the actual documentation of [ByteBuffer](http://docs.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html) – Luiggi Mendoza Jun 18 '12 at 19:50

4 Answers4

11

From the javadoc:

The hash code of a byte buffer depends only upon its remaining elements; that is, upon the elements from position() up to, and including, the element at limit() - 1.

Because buffer hash codes are content-dependent, it is inadvisable to use buffers as keys in hash maps or similar data structures unless it is known that their contents will not change.

If you are not populating the ByteBuffers, or are populating them with the same things, the hash codes will be identical.

Community
  • 1
  • 1
Michael
  • 1,239
  • 9
  • 14
5

From the ByteBuffer.java source code:

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;
}

Under your current implementation, position() always returns 0 and thus, the hashcodes are always identical. The hashcode is dependent on the content of the buffer, not on the physical object that is used to represent it.

Alex Lockwood
  • 83,063
  • 39
  • 206
  • 250
3

This is the correct behavior. Per the ByteBuffer documentation:

Two byte buffers are equal if, and only if,

They have the same element type,

They have the same number of remaining elements, and

The two sequences of remaining elements, considered independently of their starting positions, are pointwise equal.

A byte buffer is not equal to any other type of object.

So, assuming that this.size() always returns the same thing, your buffers are always equal. Per the general contract of hashCode, they must therefore all have the same hash code.

You appear to be trying to use hashCode to determine object identity - this isn't a good idea (because of how hashCode and == interact). If you need to distinguish instances of your class from each other, and need more than what the == operator gives you, you'll have to find some other way to do it.

Sbodd
  • 11,279
  • 6
  • 41
  • 42
2

ByteBuffer.hashcode lets you calculate a hash of the wrapped byte[]. In this case, the content of the newly initialized byte[] is 0 for each byte. Given that the ByteBuffer content is the same, the hashcode is the same.

maasg
  • 37,100
  • 11
  • 88
  • 115