Ruby:为什么相同的字符串有不同的哈希码?

时间:2010-04-22 01:36:57

标签: ruby hash

test = 'a'
test2 = '@a'.slice(0)
test3 = '@a'[1]

puts test.hash
puts test2.hash
puts test3.hash

输出:

100
64
97

这是一个错误还是我误解了哈希方法的工作原理?有办法解决这个问题吗?

3 个答案:

答案 0 :(得分:3)

这些表达式的结果并非都是相同的数据。 Ruby 1.8整数包含单字符索引的字符数。这已在Ruby 1.9中更改,但slice(0)返回字符串'@'的第一个字符,而不是'a'

在Ruby 1.8中(使用irb):

irb(main):001:0> test = 'a'
=> "a"
irb(main):002:0> test2 = '@a'.slice(0)
=> 64
irb(main):003:0> test3 = '@a'[1]
=> 97
irb(main):004:0> test.hash
=> 100
irb(main):005:0> test2.hash
=> 129
irb(main):006:0> test3.hash
=> 195

在Ruby 1.9.1中:

irb(main):001:0> test = 'a'
=> "a"
irb(main):002:0> test2 = '@a'.slice(0)
=> "@"
irb(main):003:0> test3 = '@a'[1]
=> "a"
irb(main):004:0> test.hash
=> 1365935838
irb(main):005:0> test2.hash
=> 347394336
irb(main):006:0> test3.hash
=> 1365935838

答案 1 :(得分:2)

原因是每个变量引用具有自己唯一哈希码的不同对象!变量test是字符串“a”,test2是整数64(字符数'@'),test3是整数97('a')。令人惊讶的是,在Ruby中,字符串的元素是整数,而不是字符串或字符。

答案 2 :(得分:1)

正如maerics所指出的,除非你为你正在使用的类定义了自己的哈希方法,否则哈希可能只是在对象本身,而不是它的内容。也就是说,您可以(并且应该)为您定义equals方法的任何类定义自己的哈希方法。

在Ruby中,String类已经为你做了这个:

irb(main):001:0> test="a"
=> "a"
irb(main):002:0> test2="a"
=> "a"
irb(main):003:0> test.hash
=> 100
irb(main):004:0> test2.hash
=> 100
irb(main):005:0> test2[0]=test.slice(0)
=> 97
irb(main):006:0> test2
=> "a"
irb(main):007:0> test2.hash
=> 100

我还没有找到Ruby的等效文本,但是这个关于Java的页面提供了一个很好的算法来生成自己的哈希代码,这些哈希代码不难为Ruby复制:http://www.javapractices.com/topic/TopicAction.do?Id=28