Java自定义排序用法

Java自定义排序用法

在Java中,我们可以使用自定义排序来对对象或数组进行排序。这可以通过实现 Comparator 接口或使用 Comparable 接口来实现。下面是两种方法的示例:


1.使用 Comparator 接口(常用)

当我们需要以不同的方式比较两个对象时,可以使用 Comparator 接口来实现自定义排序。这个接口有一个方法 compare(T o1, T o2),它接收两个泛型参数 T,并返回一个 int 类型的值。这个返回值指示了两个对象的大小关系,具体含义如下:

  • 如果返回值为负数,则表示 o1 小于 o2——不交换
  • 如果返回值为零,则表示 o1 等于 o2——不交换
  • 如果返回值为正数,则表示 o1 大于 o2——交换

当使用排序算法(如 Arrays.sort()Collections.sort())时,它们会根据 Comparator 的比较结果来决定是否交换两个元素的位置。如果返回值为负数或零,表示元素顺序已经符合要求,不需要交换;如果返回值为正数,表示元素顺序需要交换,算法会进行交换操作。

例如,在以下代码中:

Arrays.sort(array, new Comparator<Integer>() {
    @Override
    public int compare(Integer num1, Integer num2) {
        return num1 - num2;  // 升序排序
    }
});

如果 compare() 方法返回负数,则表示 num1 小于 num2,这时不会交换它们的位置。如果返回正数,则表示 num1 大于 num2,算法会交换它们的位置。

需要注意的是,如果直接返回 num1 - num2,可能会导致整数溢出问题。为了避免这个问题,可以使用 Integer.compare(num1, num2) 方法,它会考虑到溢出情况,返回正确的比较结果。

Integer.compare(num1, num2) 方法是一个静态方法,用于比较两个整数的大小。它返回一个 int 值。
在排序算法中,当使用 Integer.compare(num1, num2) 方法作为比较器时,根据返回值的不同,交换的情况如下:

  • 如果返回值为负数,则表示 num1 小于 num2,此时不进行交换。
  • 如果返回值为零,则表示 num1 等于 num2,也不进行交换。
  • 如果返回值为正数,则表示 num1 大于 num2,此时会进行交换。

需要注意的是,Integer.compare(num1, num2) 方法会考虑到整数溢出的情况,因此可以安全地使用该方法进行比较。

Arrays.sort(array, new Comparator<Integer>() {
    @Override
    public int compare(Integer num1, Integer num2) {
        return Integer.compare(num1, num2);  // 升序排序
    }
});

下面是三个不同的例子,用来说明如何使用 Comparator 接口进行自定义排序:

(1) 根据字符串长度排序

在这个例子中,我们将按照字符串长度对字符串数组进行排序。短字符串排在前面,长字符串排在后面。

import java.util.Arrays; // 导入Arrays类,提供了数组相关的工具方法
import java.util.Comparator; // 导入Comparator接口,该接口定义了比较两个对象的方法。

public class Main {
    public static void main(String[] args) {
        String[] strings = {"aaa", "bb", "c", "dddd"}; // 定义一个字符串数组

        // 使用Arrays.sort方法对字符串数组进行排序,第二个参数是一个Comparator接口实现类的实例,
        // 匿名内部类方式实现了Comparator接口,定义比较方法compare,比较规则为比较两个字符串长度大小。
        Arrays.sort(strings, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                return s1.length() - s2.length();
            }
        });

        System.out.println(Arrays.toString(strings)); // 打印排序后的字符串数组
    }
}

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

public class Main {
    public static void main(String[] args) {
        String[] strings = {"aaa", "bb", "c", "dddd"};

        // 使用Lambda表达式替换匿名内部类实现Comparator接口
        Arrays.sort(strings, (s1, s2) -> s1.length() - s2.length());

        System.out.println(Arrays.toString(strings));
    }
}


在这个例子中,我们使用了匿名内部类来实现 Comparator 接口,并在其中重写了 compare() 方法。
该方法根据字符串的长度进行排序。最后,我们使用 Arrays.sort() 方法对字符串数组进行排序,并输出排序后的结果。


(2) 根据字符串长度和字典序排序

在这个例子中,我们将按照字符串长度和字典序对字符串数组进行排序。短字符串排在前面,长字符串排在后面,如果长度相等,则按照字典序排序。

import java.util.Arrays; // 导入Arrays类,提供了数组相关的工具方法
import java.util.Comparator; // 导入Comparator接口,该接口定义了比较两个对象的方法。

public class Main {
    public static void main(String[] args) {
        String[] strings = {"aaa", "cc", "bb", "a"}; // 定义一个字符串数组

        // 使用Arrays.sort方法对字符串数组进行排序,第二个参数是一个Comparator接口实现类的实例,
        // 匿名内部类方式实现了Comparator接口,定义比较方法compare,比较规则为先比较字符串长度,长度相等时再比较字典序。
        Arrays.sort(strings, new Comparator<String>() {
            @Override
            public int compare(String s1, String s2) {
                int lenComp = s1.length() - s2.length(); // 比较字符串长度
                if (lenComp != 0) { // 如果长度不等,则返回长度差值
                    return lenComp;
                } else { // 如果长度相等,则返回字典序比较结果
                    return s1.compareTo(s2);
                }
            }
        });

        System.out.println(Arrays.toString(strings)); // 打印排序后的字符串数组
    }
}
============================================================================
import java.util.Arrays;

public class Demo02 {
    public static void main(String[] args) {
        String[] strings = { "aaa", "cc", "bb", "a" };

        // 使用Lambda表达式对字符串数组进行排序
        Arrays.sort(strings, (s1, s2) -> {
            int lenComp = s1.length() - s2.length();
            if (lenComp != 0) {
                return lenComp;
            } else {
                return s1.compareTo(s2);
            }
        });

        System.out.println(Arrays.toString(strings));
    }
}

在这个例子中,我们同样使用了匿名内部类来实现 Comparator 接口。首先,我们按照字符串的长度进行比较,如果长度相等,则再按照字典序进行比较。最后,我们使用 Arrays.sort() 方法对字符串数组进行排序,并输出排序后的结果。

Tips:

compareTo 是Java中String类的一个方法,用于比较两个字符串的大小关系。

s1.compareTo(s2) 的作用是比较字符串s1和s2的字典序(按照字符的Unicode码值进行比较)。

例如,如果s1是"aaa",s2是"aaab",那么s1.compareTo(s2)将返回一个负数,表示s1在s2之前。

需要注意的是,compareTo方法要求两个字符串必须是非空的,否则可能会抛出空指针异常。因此,在实际使用时,需要确保s1和s2都不为null。


(3)根据对象属性排序

在这个例子中,我们将按照人物的年龄对人物数组进行排序。年龄小的人排在前面,年龄大的人排在后面。

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

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

public class Main {
    public static void main(String[] args) {
        Person[] people = {
                new Person("卡卡罗特", 25),
                new Person("贝吉塔", 20),
                new Person("龟仙人", 30)
        };

        Arrays.sort(people, new Comparator<Person>() {
            @Override
            public int compare(Person p1, Person p2) {
                return p1.getAge() - p2.getAge();
            }
        });

        for (Person person : people) {
            System.out.println(person.getName() + " - " + person.getAge());
        }
    }
}

贝吉塔- 20
卡卡罗特 - 25
龟仙人 - 30

=============================================================================
public class Demo03 {
    public static void main(String[] args) {
        Person[] people = {
                new Person("Alice", 25),
                new Person("Bob", 20),
                new Person("Charlie", 30)
        };
  		// 使用Lambda表达式替换匿名内部类实现Comparator接口
        Arrays.sort(people, (p1, p2) -> p1.getAge() - p2.getAge());

        for (Person person : people) {
            System.out.println(person.getName() + " - " + person.getAge());
        }
    }
}

在这个例子中,我们定义了一个 Person 类,并创建了一个 Person 对象数组。然后,我们使用匿名内部类来实现 Comparator 接口,并在其中重写了 compare() 方法。该方法根据人物的年龄进行比较。最后,我们使用 Arrays.sort() 方法对人物数组进行排序,并输出排序后的结果。

以上就是三个例子,它们展示了如何在 Java 中使用 Comparator 接口进行自定义排序。


2.使用 Comparable 接口

import java.util.Arrays;

class Person implements Comparable<Person> {
    private String name;
    private int age;

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int compareTo(Person other) {
        // 按照年龄进行比较
        return this.age - other.age;
    }
}

public class Demo04 {
    public static void main(String[] args) {
        Person[] people = {
                new Person("Alice", 25),
                new Person("Bob", 20),
                new Person("Charlie", 30)
        };

        Arrays.sort(people);

        for (Person person : people) {
            System.out.println(person.getName() + " - " + person.getAge());
        }
    }
}

使用Comparable接口主要适用于单一的比较规则,而Comparator接口对于需要多种或动态比较规则的情况更为常用。


实战例题:(后续更新)

  • 31
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

喻师傅

谢谢您!我会继续努力创作!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值