zoukankan      html  css  js  c++  java
  • ruby中Hash的自定义key

    Hash主要使用Key中的两个函数:hash和eql? hash返回的是对象的hash值,eql?是用来对比两个对象是不是相等。

    回顾下Hash这种数据结构,其首先需要一个hash函数返回一个整数,ruby中为Fixnum,然后根据Fixnum去使用eql?判断两个object是不是相同。

    所以,如果只是改变了hash函数,就仅仅会让具有相同实例的objecthash到同一个Fixnum,但是eql?不相等,也没有办法当成同一个key。同样,如果只修改eql?,相同字段的object可能都没有办法hash到同一个Fixnum,那么同样也没有办法当作同一个key。


    为了说明这两个函数的用处,我将分四种情况讨论。

    情况1)定义一个Kiwi,不改变hash和eql?

    class Kiwi
    	attr_reader :id, :name
    
    	def initialize(id, name)
    		@id = id
    		@name = name
    	end
    end
    Kiwi.new(1, "kiwi").eql?(Kiwi.new(1, "kiwi"))  #=> false
    hash = Hash.new #=> {}
    hash[Kiwi.new(1, "kiwi")]  = 1  #=> {#<Kiwi:0x00000001ec8230 @id=1, @name="kiwi">=>1}
    hash[Kiwi.new(1, "kiwi")]     #=> nil


    从情况1中,我们可以看出在没有重写hash和eql?的情况下,虽然Kiwi的两个实例字段相同,但是不能相等,同时,hash具有相同字段的Kiwi实例,也不能得到结果。


    情况2)仅修改hash,不修改eql?

    class Kiwi
    	attr_reader :id, :name
    
    	def initialize(id, name)
    		@id = id
    		@name = name
    	end
    	def hash
    		@id.hash
    	end
    end
    Kiwi.new(1, "kiwi").eql?(Kiwi.new(1, "kiwi"))  #=> false
    hash = Hash.new #=> {}
    hash[Kiwi.new(1, "kiwi")]  = 1  #=> {#<Kiwi:0x00000000c38de0 @id=1, @name="kiwi">=>1}
    hash[Kiwi.new(1, "kiwi")]     #=> nil

    结果与情况1中相同


    情况3)仅修改eql?

    class Kiwi
    	attr_reader :id, :name
    
    	def initialize(id, name)
    		@id = id
    		@name = name
    	end
    	def eql?(other)
    		self.class.equal?(other.class) && @id == other.id && @name == other.name
    	end
    end
    Kiwi.new(1, "kiwi").eql?(Kiwi.new(1, "kiwi"))  #=> true
    hash = Hash.new #=> {}
    hash[Kiwi.new(1, "kiwi")]  = 1  #=>{#<Kiwi:0x00000000f5ba90 @id=1, @name="kiwi">=>1}
    hash[Kiwi.new(1, "kiwi")]     #=> nil

    可以看出当Kiwi两个实例变量相同的相同的时候,Kiwi即相等


    情况4)同时修改hash和eql?

    class Kiwi
    	attr_reader :id, :name
    
    	def initialize(id, name)
    		@id = id
    		@name = name
    	end
    	def eql?(other)
    		self.class.equal?(other.class) && @id == other.id && @name == other.name
    	end
    	def hash
    		@id.hash
    	end
    end
    Kiwi.new(1, "kiwi").eql?(Kiwi.new(1, "kiwi"))  #=> true
    hash = Hash.new #=> {}
    hash[Kiwi.new(1, "kiwi")]  = 1  #=>  {#<Kiwi:0x00000000b928f0 @id=1, @name="kiwi">=>1}
    hash[Kiwi.new(1, "kiwi")]     #=> 1

    这下就只要kiwi的实例变量相同,都被当成同一个key了


  • 相关阅读:
    让我们一起Go(八)
    让我们一起Go(七)
    让我们一起Go(六)
    VTemplate模板引擎的使用入门篇
    超时时间已过或服务器未响应的解决方法
    SQL Server 2005使用BCP命令将数据表导出到Excel第一行包括表头
    VTemplate模板引擎的使用进阶篇
    VTemplate模板引擎的使用认识篇
    免费开源的模板引擎VTemplate
    .NET 4.5 中新提供的压缩类
  • 原文地址:https://www.cnblogs.com/java20130722/p/3206853.html
Copyright © 2011-2022 走看看