1

I want to generate, in Ruby, the same hash code returned by Java's String.hashCode method. What approach would be most elegant? Java's String hashCode implementation is described here: http://docs.oracle.com/javase/6/docs/api/java/lang/String.html#hashCode%28%29

Marcin Nabiałek
  • 109,655
  • 42
  • 258
  • 291
fooledbyprimes
  • 999
  • 1
  • 11
  • 29

3 Answers3

5

This is my version. It does the same as javascript hashCode. Note the 32 bit conversion trick packing and unpacking:

  def hash_code(str)
    str.each_char.reduce(0) do |result, char|
      [((result << 5) - result) + char.ord].pack('L').unpack('l').first
    end
  end
Ungue
  • 442
  • 5
  • 14
3

Here is a simple implementation.

def jhash(str)
  result = 0
  mul = 1
  max_mod = 2**31 - 1

  str.chars.reverse_each do |c|
    result += mul * c.ord
    result %= max_mod
    mul *= 31
  end

  result  
end

And some sample runs

jhash("aa")
3104

jhash("")
0 

jhash("polygenelubricants") #Java returns -2147483648
1283535072

Note that the java implementation returns a int which is 32 bits wide(31 bits for unsigned). The Java hashcode implementation may also return negative values. This implementation will not mimic java's negative hashcode behaviour. Instead it will return a whole number between 0 and 2**31-1(Integer.MAX_VALUE)

bsd
  • 2,707
  • 1
  • 17
  • 24
-2

This is an example that returns the same result as hashCode() in java

TWO_31 = 2 ** 31
TWO_32 = 2 ** 32

def java_hash_code(str)
  size = str.size
  hash = 0
  str.chars.each_with_index do |ch, i|
    hash += ch.ord * (31 ** (size-(i+1)))
    hash = hash % TWO_32 - TWO_31
  end
  hash
end
dongqs
  • 1