先描述一下我的element,看源码:
private static class Solution implements Comparable<Solution>{
final int width;
final int height;
double lwr; //长宽比(length-width ratio)
/* constructors */
public Solution(int width , int height){
this.width = width;
this.height = height;
calculateLws();
}
private void calculateLws(){
if(this.width==0.0||height==0.0)
throw new IllegalArgumentException("width or height of solution can't be 0");
this.lwr = div(this.height , this.width , 4);
/*
if(CommonProps.Debug)
System.out.println(this.height+"\t"+this.width+"\t"+lwr);
*/
}
private double div(double d1 , double d2 , int scale){
BigDecimal bd1 = new BigDecimal(Double.toString(d1));
BigDecimal bd2 = new BigDecimal(Double.toString(d2));
return bd1.divide(bd2,scale
,BigDecimal.ROUND_HALF_UP)
.doubleValue();
}
public int compareTo(Solution s) {
//if(this.lwr == s.lwr)
if(this.width==s.width && this.height==s.height)
return 0;
else if(this.lwr > s.lwr)
return 1;
else
return -1;
}
@Override
public int hashCode(){
int result = 18;
result = 31*result +width;
result = 31*result +height;
return result;
}
@Override
public boolean equals(Object obj){
if(this == obj)
return true;
if(!(obj instanceof Solution))
return false;
Solution s = (Solution)obj;
return width==s.width&&height==s.height;
}
}
这是一个分辨率的类,其中lwr
是长宽比,是根据width和height计算得到的值。
在原本的compareTo方法中,判断相等是这样的:
if(this.lwr==s.lwr)
return true;
但是后来出现了问题:如果两个Solution的长宽比是相等的,但是长度和宽度都不同,这时候会错误的返回true。
这个问题导致了在使用TreeSet时,明明没有这个Solution,但是contains方法返回true。
解决方案就是使用width和height来比较是否相等:
if(this.width==s.width && this.height==s.height)
return 0;
想到了Effective Java
中的一句话:不需要比较冗余域,也就是从关键域计算获得的那些域
。虽然这句话是在重写equals方法时提到的,并且只是为了提高equals的性能,但是现在看来,在compareTo中一样试用,而且其导致的不仅仅是性能问题。