toString、equals和hashCode重写


 

public class TestBean {
	private byte para1;
	private long para2;
	private double para3;
	private float para4;
	private int[] para5;
	private String para6;
	public TestBean() {
		
	}
	public TestBean(byte para1, long para2, double para3, float para4, int[] para5, String para6) {
		this.para1 = para1;
		this.para2 = para2;
		this.para3 = para3;
		this.para4 = para4;
		this.para5 = para5;
		this.para6 = para6;
	}
	
	@Override
	public String toString() {
		return "TestBean [para1=" + para1 + ", para2=" + para2 + ", para3="
				+ para3 + ", para4=" + para4 + ", para5="
				+ Arrays.toString(para5) + ", para6=" + para6 + ", hashCode()="
				+ hashCode() + "]";
	}
	
	@Test
	public void test(){
		System.out.print(1231321>>>32);
	}
	
	@Override
	public boolean equals(Object obj) {
		if(obj == null)
			return false;
		if(obj == this)
			return true;
		if(obj instanceof TestBean){
			TestBean testBean = (TestBean) obj;
			return testBean.para1 == para1 && testBean.para2 == para2 && Double.doubleToLongBits(testBean.para3) == Double.doubleToLongBits(para3) && 
					Float.floatToIntBits(testBean.para4) == Float.floatToIntBits(para4) && Arrays.equals(testBean.para5, para5) &&
					((testBean.para6 == null && para6 == null) || (testBean.para6 != null && testBean.para6.equals(para6)));
		}
		return false;
	}
	
	@Override
	public int hashCode() {
		final int base = 31;
		int result = 17;
			result = base*result + para1;
			result = base*result + (int)(para2^(para2>>>32));
		long temp = Double.doubleToLongBits(para3);
			result = base*result + (int)(temp^(temp>>>32));
			result = base*result + Float.floatToIntBits(para4);
			result = base*result + Arrays.hashCode(para5);
			result = base*result + para6 == null ? 0 : para6.hashCode();
		return result;
	}
}

1.重写toString:

    把本来的TestBean@d5682s78,这样的日志输出内容,改成其他的更清晰的方式。有两张一种是上面的那种方式,还有一种是格式化的输出方式。

2.重写equals:

    重写equals必须重写hashCode。因为这个方法遵循Object的通用约定就是:

    a.同一个对象多次调用每次返回的hashCode都是相等的,而同一类型的不同对象多次被调用返回的hashCode可以不同

    b.equals相等的hashCode必定相等

    c.hashCode相等的,equals可以不等。

    equals只是两个对象逻辑上相等,并不是比较在内存中的地址值,因此不同的对象equals也可能相等。

3.重写hashCode:

    选择31作为乘数的基数,有两个原因:

        a.31是一个传统的奇数。

        b.31*x=x<<5-x

    如上述代码,hashCode重写时,为了保证良好的散列性,遵循以下原则:

        a.byte、char、short类型的数据要转化为int再相加

        b.long可以int(longnum^(longnum>>>32))相加

        c.float先转化为int,Float.floatToIntBits(fnum)

        d.Double先转化为long,Double.doubleToLongBits(dnum),剩下的操作同b

        e.Array可用Arrays.hashCode(arr)得到hashCode值

        f.Object先计算出Object的hashCode。

    通过上述步骤得到了良好散列性的hashCode但是影响了速度。因此可以稍微更改一下。加一个预存的hash值,这样不管这个对象被调用多少次,hashCode只计算一次。

    调整后:

	private volatile int hashCode = 0; //加个全局变量,volatile的意思不安全的,
                               //告诉jvm取消内存拷贝,取这个值的时候直接到内存中取
    @Override
	public int hashCode() { //调整后的hashCode方法
		
		int result = hashCode;
		
		if(result == 0){
			i++;
			final int base = 31;
			result = 17;
			result = base*result + para1;
			result = base*result + (int)(para2^(para2>>>32));
		long temp = Double.doubleToLongBits(para3);
			result = base*result + (int)(temp^(temp>>>32));
			result = base*result + Float.floatToIntBits(para4);
			result = base*result + Arrays.hashCode(para5);
			result = base*result + ((para6 == null) ? 0 : para6.hashCode());
			hashCode = result; //在这里把计算出来的result值赋给全局变量hashCode
		}
		
		return hashCode;
	}

还可以采用“延迟加载”,但这样的方法会造成代码复杂性提高,代码可阅读行降低。

转载于:https://my.oschina.net/wliming/blog/678081

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值