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:
把本来的[email protected],这样的日志输出内容,改成其他的更清晰的方式。有两张一种是上面的那种方式,还有一种是格式化的输出方式。
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
上一篇: 【Object 类】 toString、equals 、hashCode
下一篇: java.io.EOFException: Unexpected EOF read on the socket
推荐阅读
-
JavaSE的包装类,自动装箱和自动拆箱 ,字符窜转换,toString(),equals(), hashCode()的区别
-
why在重写equals时还必须重写hashcode方法分享
-
why在重写equals时还必须重写hashcode方法分享
-
重写hashCode()和equals()方法详细介绍
-
重写hashCode()和equals()方法详细介绍
-
java中hashCode和equals什么关系,hashCode到底怎么用的
-
Java连载57-equals重写、finalize方法、hashCode方法
-
说说hashCode() 和 equals() 之间的关系?
-
关于重写equals()和hashCode()的思考
-
一文搞懂hashCode()和equals()方法的原理