java自定义排序

文章展示了如何在Java中使用自定义Comparator对包含学生年龄和身高的数组进行排序。首先按年龄升序,年龄相同则按身高升序。示例代码中使用了`Arrays.sort`配合匿名内部类实现,比较时利用`Integer.compare`和`Double.compare`避免浮点数比较误差。文章还提到了`Arrays.sort`和`Collections.sort`的区别,前者适用于数组,采用快速排序,后者适用于实现了List接口的集合,采用归并排序。
摘要由CSDN通过智能技术生成

有一个类,存储学生信息,第一个成员是年龄,第二个是身高,有一个学生容器数组,按照自定义规则进行排序,首先按照年龄升序排序,年龄相同的,按照身高升序排序,下面是示例代码:

import java.util.Arrays;
import java.util.Comparator;

class Student {
    private int age;
    private double height;

    public Student(int age, double height) {
        this.age = age;
        this.height = height;
    }

    public int getAge() {
        return age;
    }

    public double getHeight() {
        return height;
    }
}

public class Students {
    public static void main(String[] args) {
        Student[] students = new Student[5];
        students[0] = new Student(20, 170.5);
        students[1] = new Student(18, 165.6);
        students[2] = new Student(20, 170.4);
        students[3] = new Student(19, 165.4);
        students[4] = new Student(18, 165.5);

        // 使用自定义规则对学生数组进行排序
        Arrays.sort(students, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                // 首先按照年龄升序排序
                int ageComparison = Integer.compare(s1.getAge(), s2.getAge());
                if (ageComparison != 0) {
                    return ageComparison;
                }

                // 年龄相同,按照身高升序排序
                return Double.compare(s1.getHeight(), s2.getHeight());
            }
        });

        // 打印排序后的学生信息
        for (Student student : students) {
            System.out.println("Age: " + student.getAge() + ", Height: " + student.getHeight());
        }
    }
}

输出:

Age: 18, Height: 165.5
Age: 18, Height: 165.6
Age: 19, Height: 165.4
Age: 20, Height: 170.4
Age: 20, Height: 170.5

注意其中在声明比较规则的匿名内部类时我们使用了

return Double.compare(s1.getHeight(), s2.getHeight());

而不是

return (int)(s1.getHeight()- s2.getHeight());

为什么呢,首先我们知道Array的sort函数在升序时的规则为,当左边的数大于右边的数应当返回正整数,反之返回负整数,如果相等则返回0。而当俩个浮点数的差不到1时,强转int得到的值为0,会导致错误排序,而java已经考虑了这点给我们提供了方便的比较函数。

可以打开库函数看看Double.compare的逻辑:

public static int compare(double d1, double d2) {
        if (d1 < d2)
            return -1;           // Neither val is NaN, thisVal is smaller
        if (d1 > d2)
            return 1;            // Neither val is NaN, thisVal is larger

        // Cannot use doubleToRawLongBits because of possibility of NaNs.
        long thisBits    = Double.doubleToLongBits(d1);
        long anotherBits = Double.doubleToLongBits(d2);

        return (thisBits == anotherBits ?  0 : // Values are equal
                (thisBits < anotherBits ? -1 : // (-0.0, 0.0) or (!NaN, NaN)
                 1));                          // (0.0, -0.0) or (NaN, !NaN)
}

而且不仅仅是浮点数,在整数类型排序时也最好使用Integer.compare,因为自己手动对两个int数据相减的话容易导致数据超范围。


另外,注意我们在上面使用的排序api是Arrays.sort(),还有一种常用的排序api是Collections.sort(),它们主要区别在于它们所操作的数据类型和实现方式:

数据类型:
Arrays.sort(): 这个方法是针对数组的排序。它可以用于基本数据类型数组(如 int[]、double[] 等)和对象类型数组(如 String[]、Integer[] 等)。
Collections.sort(): 这个方法是针对集合类的排序。它只能用于实现了 List 接口的集合,例如 ArrayList、LinkedList 等。

实现方式:
Arrays.sort(): 对数组排序采用的是经过优化的快速排序(Dual-Pivot Quicksort)算法。在大多数情况下,它比较高效,并且具有稳定的排序性能。
Collections.sort(): 对集合排序采用的是归并排序(Merge Sort)算法。尽管归并排序在大多数情况下也是高效的,但它需要额外的空间来执行排序操作。由于集合是动态数据结构,可能需要频繁地进行内存分配和释放,因此在排序大型集合时可能稍慢一些。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值