关于Comparable的compareTo的正确写法

先描述一下我的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中一样试用,而且其导致的不仅仅是性能问题。

### 回答1: compareToComparable都是Java中用于比较对象的接口和方法。 Comparable是一个接口,它定义了一个compareTo()方法,用于比较对象的大小。实现Comparable接口的类可以使用Collections.sort()方法进行排序。 compareTo()方法返回一个整数值,表示当前对象与另一个对象的大小关系。如果当前对象小于另一个对象,则返回负整数;如果当前对象等于另一个对象,则返回;如果当前对象大于另一个对象,则返回正整数。 例如,如果我们有一个Student类实现了Comparable接口,我们可以使用以下代码对学生列表进行排序: List<Student> students = new ArrayList<>(); students.add(new Student("Tom", 20)); students.add(new Student("Jerry", 18)); Collections.sort(students); 这将根据学生的年龄对学生列表进行排序。 compareTo()方法的实现可以根据需要进行自定义,以实现不同的比较逻辑。 相比之下,Comparator是一个接口,它定义了一个compare()方法,用于比较两个对象的大小。Comparator接口可以用于对任何类的对象进行排序,而不需要实现Comparable接口。 与compareTo()方法不同,compare()方法需要接收两个参数,分别是要比较的两个对象。compare()方法的返回值与compareTo()方法相同,表示两个对象的大小关系。 例如,如果我们有一个Student类,但它没有实现Comparable接口,我们可以使用以下代码对学生列表进行排序: List<Student> students = new ArrayList<>(); students.add(new Student("Tom", 20)); students.add(new Student("Jerry", 18)); Comparator<Student> ageComparator = new Comparator<Student>() { @Override public int compare(Student o1, Student o2) { return o1.getAge() - o2.getAge(); } }; Collections.sort(students, ageComparator); 这将根据学生的年龄对学生列表进行排序,而不需要Student类实现Comparable接口。 总之,compareToComparableJava中用于比较对象的接口和方法,它们可以帮助我们对对象进行排序和比较。其中,Comparable接口适用于实现了Comparable接口的类,而Comparator接口适用于任何类的对象。 ### 回答2: "compareTo" 和 "comparable" 是Java中用于比较对象的两个相关概念。 首先,"comparable" 是一个接口,当一个类实现了 "comparable" 接口时,它表明该类的实例是可比较的。实现 "comparable" 接口的类必须重写 "compareTo" 方法,该方法根据对象的特定属性来定义比较规则。该方法需要返回一个整数值,表示比较结果的正负或零。通过实现 "comparable" 接口,我们可以在使用 "Collections" 类进行排序等操作时对对象进行比较。 而 "compareTo" 是一个用于比较两个对象的方法。它可以在一个实现了 "comparable" 接口的类的对象上调用。 "compareTo" 方法接受一个对象作为参数,并根据实现类中定义的比较规则,比较当前对象与参数对象。如果当前对象小于参数对象,方法会返回负数;如果当前对象大于参数对象,方法会返回正数;如果两个对象相等,方法会返回零。 总结起来,"comparable" 是一个接口,用于标识一个类的实例可比较,并要求实现类必须重写 "compareTo" 方法。"compareTo" 方法则是在实现了 "comparable" 接口的类的对象上调用,用于比较对象并返回比较结果的方法。通过实现 "comparable" 接口和重写 "compareTo" 方法,我们可以实现对象的自定义比较规则,并在排序、集合操作等情况下使用。 ### 回答3: compareToComparableJava中用于比较对象的两个概念。 compareTo是一个方法,用于实现对象之间的比较。它是Comparable接口中定义的方法之一。compareTo方法接收一个参数,用于与当前对象进行比较。它根据对象的属性值来判断两个对象的大小关系。如果当前对象小于传入的对象,则返回负数;如果当前对象等于传入的对象,则返回0;如果当前对象大于传入的对象,则返回正数。这个方法常常用于对对象进行排序,比如使用Collections.sort方法对一个实现了Comparable接口的类的对象进行排序。 Comparable是一个接口,用于比较对象的大小。实现了Comparable接口的类必须实现compareTo方法,来定义对象的比较规则。一般来说,实现了Comparable接口的类的对象可以进行自然排序,即按照某种规则进行排序。比如,对于整数而言,自然排序是按照数值的大小进行排序;对于字符串而言,自然排序是按照字典顺序进行排序。当我们需要对某个类的对象进行排序时,可以让该类实现Comparable接口,然后通过compareTo方法进行比较和排序。 综上所述,compareToComparableJava中用于比较对象的两个概念。其中,compareTo是一个方法,用于实现对象之间的比较;Comparable是一个接口,用于定义对象的自然排序规则。通过实现Comparable接口并实现compareTo方法,我们可以对实现了Comparable接口的类的对象进行比较和排序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值