Ruby:为什么相同的字符串有不同的哈希码?
问题描述:
test = 'a'
test2 = '@a'.slice(0)
test3 = '@a'[1]
puts test.hash
puts test2.hash
puts test3.hash
100
64
97
这是bug还是我误解散列法是如何工作的?有没有办法来解决这个问题?
答
这些表达式的结果并不都是相同的数据。 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
答
原因是每个变量引用不同的对象与自己唯一的哈希码!变量test
是字符串“a”,test2
是整数64(字符数字'@'),并且test3
是整数97('a')。令人惊讶的是,在Ruby中,字符串的元素是整数,而不是字符串或字符。
答
由于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