test = 'a'
test2 = '@a'.slice(0)
test3 = '@a'[1]
puts test.hash
puts test2.hash
puts test3.hash
输出:
100
64
97
这是一个错误还是我误解了哈希方法的工作原理?有办法解决这个问题吗?
答案 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