zoukankan      html  css  js  c++  java
  • java 覆盖hashCode()深入探讨 代码演示样例

    java 翻盖hashCode()深入探讨 代码演示样例

    package org.rui.collection2.hashcode;
    /**
     * 覆盖hashcode
     * 设计HashCode时最重要的因素 就是:不管何时,对同一个对象调用HashCode都应该产生相同的值,
     * 假设你的HashCode方法依赖于对象中易变的数据,用户就要当心了,由于此数据发生变化 时
     * HashCode就会生成一个不同的散列码,相当于产生一个不同的健
     * 此外 也不应该使HashCode依赖于具有唯一性的对象信息,尤其是使用this的值,这仅仅能非常糟糕,
     * 由于这样做无法生成一个新的健,使这与Put中原始的健值对中的健相同,它的默认的HashCode使用的是对象的地址
     * 所以 应该 使用对象内有意义的识别信息
     * 
     * 下面以String类为例 String对象都 映射到同一块内存域,
     *  所以 new String("hello") 生成的两个实例 ,尽管是相互独立的,
     *  可是对它们使用HashCode应该生成相同的结果,下面演示样例可以看到 
     *  对String而言,HashCode明显是基于String的内容的,
     *  
     *  因此 要想使HashCode有用,它必须 速度快,而且必须有意义。也就是说,它必须基于对象的内容生成的散列码,
     *  记得吗,散列码不必是独一无二的 (应该更关注生成速度,而不是唯一性)
     *  但HashCode和Equals 必须可以全然确定对象的身份
     *  所以散列码生成的范围并不重要,仅仅要是int就可以
     *  还有别一个影响因素,好的HashCode应该产生分布均匀的散列码
     *  
     *  
     * @author lenovo
     *
     */
    
    public class StringHashCode {
    	public static void main(String[] args) {
    		String[] hello="Hello Hello".split(" ");
    		System.out.println(hello[0].hashCode());
    		System.out.println(hello[1].hashCode());
    	}
    }
    /**output:
    69609650
    69609650
    */
    

    package org.rui.collection2.hashcode;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    /**
     * 覆盖hashcode
     * 
     * 在Effective java programming language guide ....这本书 为如何写出一份像样的hashcode给出了基本指导
     *  1,int变量result 赋予某个非零值 常 量,
     *  2,为对象内每一个有意义的域f(即每一个能够做equlas操作的域) 计算一个int散列码c
     *  ----------------------------------------- -----------------------------------------
     *  域类型                                                   计算
     *  ----------------------------------------- -----------------------------------------
     *  boolean                  c=(f?0:1)
     *  byte,char,shor或int       c=(int)f
     *  long                     c=(int)(f^(f>>>32))
     *  float                    c=Float.floatToIntBits(f);      依据 IEEE 754 浮点“单一格式”位布局,返回指定浮点值的表示形式
     *  double                   c=Double.doubleToLongBits(f);  
     *  Object 其equals调用这个域的equlas          c=f.hashCode();
     *  数组                                                      对每一个元素应用上述规则
     *  
     *  3,合并计算得到的散列码
     *  4,返加result
     *  5检查hashcode最后生的结果。确保同样的地象有同样的散列码
     *   ----------------------------------------- -----------------------------------------
     *  
     *  
     * CountedString是由一个String和id组成,此id代表包括同样String的CountedString对象的编号
     * 全部的String被存储在ArrayList中,在构造器中通过迭代遍历此ArrayList完毕对Id的计算
     * 
     * hashcode and equals都是基于CountedString的两 个域来生成的结果,假设它们仅仅是基于String或仅仅基于Id
     * 不同的对象就可能产生同样的值
     * 
     * 在Main中使用了同样的String,创建了多个CountedString对象,这说明,尽管String同样 ,
     * 但因为Id不同,所以使得它们的散列码并不同样,
     * @author lenovo
     *
     */
    public class CountedString {
    	private static List<String> created = new ArrayList<String>();
    	private String s;
    	private int id = 0;
    
    	public CountedString(String str) {
    		s = str;
    		created.add(s);
    		// id is the total numbe of instances
    		// of this string in by CountedString
    		for (String s2 : created) {
    			if (s2.equals(s))
    				id++;
    		}
    	}
    
    	public String toString() {
    		return "String:" + s + "  id:" + id + " hashCode:" + hashCode();
    	}
    	
    	public int hashCode()
    	{
    		//the very simple approach
    		//return s.hashCode()*id;
    		//using joshua bloch's recipe//使用joshua bloch的配方
    		int result=17;
    		//合并计算得到散列码
    		result=37*result+s.hashCode();
    		result=37*result+id;
    		return result;
    	}
    	
    	public boolean equals(Object o) {
    		return o instanceof CountedString&&
    				s.equals(((CountedString)o).s)&&
    				id==((CountedString)o).id;
    
    	}
    	public static void main(String[] args) {
    		Map<CountedString,Integer> map=new HashMap<CountedString,Integer>();
    		CountedString[] cs=new CountedString[5];
    		for(int i=0;i<cs.length;i++)
    		{
    			cs[i]=new CountedString("hi");
    			map.put(cs[i], i);//autobox int->Integer			
    		}
    		System.out.println(map);
    		for(CountedString cstring:cs)
    		{
    			System.out.println("Looking up"+cstring);
    			System.out.println("map.get(cstring):"+map.get(cstring));
    		}
    	}
    
    }
    

    package org.rui.collection2.hashcode;
    /**
     * 覆盖hashCode
     * 
     * compareTo 方法有一个比較结构,因此它会产生一个排序序列,排序的规则首先依照实际类型排序
     * 然后假设有名字的话,依照name排序,最后依照创建的顺序排序,
     * @author lenovo
     *
     */
    public class Individual implements Comparable<Individual>{
    
    	private static long counter=0;
    	private final long id=counter++;
    	private String name;
    	
    	public Individual(String name){this.name=name;}
    	public Individual(){}
    	public String toString(){
    		return getClass().getSimpleName()+
    				(name==null?"":" "+name);
    	}
    	public long id(){return id;}
    	public boolean equals(Object o){
    		return o instanceof Individual&&
    				id==((Individual)o).id;
    	}
    	public int hashCode(){
    		int result=17;
    		if(name!=null)
    			result=37*result+name.hashCode();
    			result=37*result+(int)id;
    		return result;
    	}
    	@Override
    	public int compareTo(Individual o) {
    		String first=getClass().getSimpleName();
    		String argFirst=o.getClass().getSimpleName();
    		int firstCompare=first.compareTo(argFirst);
    		if(firstCompare!=0)
    		{
    			return firstCompare;
    		}
    		if(name!=null && o.name!=null)
    		{
    			int secondCompare=name.compareTo(name);
    			if(secondCompare!=0)
    				return secondCompare;
    		}
    		
    		return (o.id<id?-1:(o.id==id?0:1));
    	}
    
    }
    

    package org.rui.collection2.hashcode;
    
    import java.util.*;
    
    import org.rui.classts.Pet;
    import org.rui.classts.chilnd.*;
    
    /**
     * 
     * 以下的演示样例说明了它怎样工作的;
     * 
     * 因为全部的寵物都有名字,因此它們首先依照類型排序,然后在同類型中依照 名字排序
     * 為新類編寫正確的hashCode和equals非常须要技巧,Apache的jakarta commons項目中有許多工具能够人幫助你完毕此事
     * @author lenovo
     *
     */
    
    public class IndvidualTest {
    
    	public static void main(String[] args) {
    		//Set<Individual> pets=new TreeSet<Individual>();
    		Pet p=new Cat("猫");
    		Pet p1=new Dog("狗");
    		Pet p2=new EgyptianMan("EgyptianMan");
    		Pet p3=new Manx("马恩岛猫");
    		Pet p4=new Pug("巴哥犬");
    	
    		//一个人有非常多宠物
    		Map<Individual,List<? extends Pet>> list2=new HashMap<Individual,List<? extends Pet>>(); 
    		
    		Individual in=new Individual("Dawn");
    		Individual in2=new Individual("東方不敗");
    		list2.put(in, Arrays.asList(p,p1,p2,p3,p4));
    		list2.put(in2, Arrays.asList(p2,p3,p4));
    		
    		System.out.println(list2);//輸出這個人的寵物
    		
    		//查找Dawn的寵物
    		List<? extends Pet> l=list2.get(in);
    		System.out.println(l);
    		
    		
    	}
    }
    /**output:
    {Individual 東方不敗=[Pet [name=EgyptianMan], Pet [name=马恩岛猫], Pet [name=巴哥犬]],
     Individual Dawn=[Pet [name=猫], Pet [name=狗], Pet [name=EgyptianMan], Pet [name=马恩岛猫], Pet [name=巴哥犬]]}
    [Pet [name=猫], Pet [name=狗], Pet [name=EgyptianMan], Pet [name=马恩岛猫], Pet [name=巴哥犬]]
     */
    


  • 相关阅读:
    Java【第二篇】基本语法之--进制、运算符
    Java【第一篇】基本语法之--关键字、标识符、变量及分类、数据类型及转换
    安装运行zookeeper的坑
    部署java应用的几种方式
    解决sudo用户找不到环境变量的问题
    Python装饰器详解
    filebeat开启自带模块收集日志如何辨别日志来源等
    使用elasticsearch7.3版本在一台主机上部署多个实例组建集群
    redis 集群搭建
    Kibana多用户创建及角色权限控制
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/3826874.html
Copyright © 2011-2022 走看看