java hashcode 例子_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 created = new ArrayList();

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 map=new HashMap();

CountedString[] cs=new CountedString[5];

for(int i=0;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{

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

}

}

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 pets=new TreeSet();

Pet p=new Cat("猫");

Pet p1=new Dog("狗");

Pet p2=new EgyptianMan("EgyptianMan");

Pet p3=new Manx("马恩岛猫");

Pet p4=new Pug("巴哥犬");

//一个人有非常多宠物

Map> list2=new HashMap>();

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=巴哥犬]]

*/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值