假设一个例子
一个罪犯类,有身高,体重,血型等属性~
身高height的范围为 0~255(cm).
体重weight的范围为 0~255(kg).
血型blood用五个数表示即可 0~4 : O、A、B、AB、不详.
那么问题来了.
1.如何节约对象在堆空间的大小?
如果用byte(-128~127)来表示属性,则可以节约空间,那么怎样实现int->byte以及byte->int的转换?
2.如果用byte作为属性类型的话,hashcode()如何实现?
hashcode用于标识两个对象是否不同,hash不同,则对象不同.
所以hashcode来自于对象有特征的属性.(与其它对象不同的属性).
hashcode()返回值为int,如何将三个byte属性组合为一个int型并返回?
如果单纯相加并返回一个整型,(180cm+160kg == 185cm+155kg),则会出现不同对象拥有同一hashcode.
那么如何避免这种情形?
问题1:
byte的范围(-128~127),size为255,而height、weight的范围(0~256)也为255.
所以用byte表示height、weight只需做好两者之间的转换.即byte(-128~127)<<===>>int(0~255)
int===>byte
int(0~127)===>byte(0~127)
int(128~255)===>byte(-128~-1)
所以只需将对应关系转换回来即可
byte===>int
byte(0~127)===>int(0~127)
byte(-128~-1)===>int(-128~-1) [强制类型转换]
注意:强制类型转换byte===>int时,当byte为负数时,转换的结果与我们期望的byte(-128~-1)===>int(128~255)不同,所以要采用其他转换方式
例如:
-127十进制
byte表示: 1000 0001
int表示:1111 1111 1111 1111 1111 1111 1000 0001
根据期望byte(-128~-1)===>int(128~255)
-127应对应129
129
int表示:0000 0000 0000 0000 0000 0000 1000 0001
所以,应将byte强制转换为int在与0xFF相与.这样的到的结果与期望相同
问题2
对于int(4byte),我们只需将3个byte属性组合拼接为一个int值,即可保证不同属性对象hashcode一定不同
int值 = [符号位+7bit][byte][byte][byte]
我们只需将height、weight、blood属性放入低位三个byte.
做法:
1.将每个byte转换为对应的int数,(与题1的期望相同).
2.将的到的每个int数进行位移操作.(分别移动16位,8位,0位).
3.将三个数相加作为hashcode返回.
实现代码:
package com.it18zhang;
//罪犯类
public class Criminal {
private byte height;
private byte weight;
private byte blood;
private String home;
//构造函数
public Criminal(byte height, byte weight, byte blood, String home) {
super();
this.height = height;
this.weight = weight;
this.blood = blood;
this.home = home;
}
//javabean
public byte getHeight() {
return height;
}
public void setHeight(byte height) {
this.height = height;
}
public byte getWeight() {
return weight;
}
public void setWeight(byte weight) {
this.weight = weight;
}
public byte getBlood() {
return blood;
}
public void setBlood(byte blood) {
this.blood = blood;
}
public String getHome() {
return home;
}
public void setHome(String home) {
this.home = home;
}
@Override
//hashCode,要实现byte的回转
public int hashCode() {
int heightBits = height & 0x000000FF;
int weightBits = weight & 0x000000FF;
int bloodBits = blood & 0x000000FF;
heightBits = heightBits << 16;
weightBits = weightBits << 8;
return heightBits |weightBits | bloodBits;
}
@Override
//equals方法,注意健壮性
public boolean equals(Object obj) {
if(obj == null)
return false;
if(obj == this)
return true;
boolean homeEqu = false;
boolean hashEqu = false;
if(this.getClass() == obj.getClass()){
Criminal c = (Criminal)obj;
if(home.equals(c.home)){
homeEqu = true;
}
if(this.hashCode()==obj.hashCode()){
HashEqu = true;
}
}
return HashEqu&&homeEqu;
}
else{
return false;
}
}
}