Java通过Comparable接口或者Comparator接口实现自定义排序

一、Comparable接口

Arrays类中的sort方法承诺可以对对象数组进行排序,但要对象所属的类必须实现Comparable接口。

public interface Comparable<T> {
    /**   
     * @param   o the object to be compared.
     * @return  a negative integer, zero, or a positive integer as this object
     *          is less than, equal to, or greater than the specified object.
     */
    public int compareTo(T o);
}

假设希望使用Arrays类的sort方法对Employee对象数组进行排序,Employee类就必须实现Comparable接口

class Employee implements Comparable {
	private Integer age;
	private Integer salary;//对薪水进行排序
	public int compareTo(Object otherObject) {
		Employee other = (Employee) otherObject;
		//这里使用了静态Double.compare()方法。如果第一个参数小于第二个参数,返回负值
		return Double.compare(salary, other.salary);
	}
}

总是对Object进行类型转换感觉挺不方便的,可以为泛型Comparable接口提供一个类型参数

class Employee implements Comparable<Employee> {
	private Integer age;
	private double salary;//对薪水进行排序
	public int compareTo(Employee other) {
		//Employee other = otherObject;
		//这里使用了静态Double.compare()方法。如果第一个参数小于第二个参数,返回负值
		return Double.compare(salary, other.salary);
	}
}

调用:

Employee[] staff = new Employee[10];
//省略给10个Employee对象赋值
Arrays.sort(staff);

二、Comparator接口

前面已经通过实现了Comparable接口的类的实例。来对一个对象数组进行排序。例如,可以对一个字符串数组排序,因为String类实现了Comparable ,而且String.compareTo方法可以按字典顺序比较字符串。
现在我们希望按长度递增的顺序对字符串进行排序,而不是按字典顺序进行排序。肯定不能让String类用两个不同的方式实现compareTo方法,更何况,String类也不应该由我们修改。

所以,Arrays.sort方法还有第二个版本,有一个数组和一个比较器(Comparator)作为参数,比较器是实现了Comparator接口的类的实例。

public interface Comparator<T> {
    /**
     * @param o1 the first object to be compared.
     * @param o2 the second object to be compared.
     * @return a negative integer, zero, or a positive integer as the
     *         first argument is less than, equal to, or greater than the
     *         second.
     */
    int compare(T o1, T o2);

要按长度比较字符串,可以定义一个实现了Comparator的类

class LengthComparator implements Comparator<String> {
	public int compare(String first, String second) {
		return first.length() - second.length();
	}
}

具体完成比较时,需要建立一个实例:

LengthComparator comp = new LengthComparator();
if (comp.compare(words[i], words[j]) > 0)
...........

将这个比较与words[i].compareTo(words[j])进行比较。这个compare方法要在比较器对象上调用,而不是在字符串本身身上调用。
要对数组排序,需要为Arrays.sort方法传入一个LengthComparator对象:

String[] friends = {"tom", "Mary", "Peter"};
Arrays.sort(friends, new LengthComparator());

完整代码如下:

class LengthComparator implements Comparator<String> {
    public int compare(String first, String second) {
        return first.length() - second.length();
    }
}
public class Test {
    public static void main(String[] args) {
        String[] friends = {"tom", "Mary", "Peter"};
        Arrays.sort(friends, new LengthComparator());
        System.out.println(Arrays.toString(friends));
    }
}

使用局部内部类改写

public class Test {
    //因为main方法是static方法,故将该类加上static修饰
    static class LengthComparator implements Comparator<String> {
        public int compare(String first, String second) {
            return first.length() - second.length();
        }
    }
    public static void main(String[] args) {
        String[] friends = {"tom", "Mary", "Peter"};
        Arrays.sort(friends, new LengthComparator());
        System.out.println(Arrays.toString(friends));
    }
}

使用匿名内部类改写

在使用局部内部类时,可以进一步。假设只想创建这个类的一个对象,甚至不需要为类指定名字,这就是匿名内部类。
匿名内部类的语法为:

//SuperType可以使接口,也可以是类
new SuperType(construction parameters) {
	inner class methods and data
	}

程序为:

public class Test {
    public static void main(String[] args) {
        String[] friends = {"tom", "Mary", "Peter"};
        //这里SuperType是Comparator接口
        Arrays.sort(friends, new Comparator<String>() {
            public int compare(String first, String second) {
                return first.length() - second.length();
            }
        });
        System.out.println(Arrays.toString(friends));
    }
}

使用lambda表达式改写

public class Test {
    public static void main(String[] args) {
        String[] friends = {"tom", "Mary", "Peter"};
        Arrays.sort(friends, (first, second) -> {
                return first.length() - second.length();
            }
        );
        System.out.println(Arrays.toString(friends));
    }
}

这样代码就很简洁了。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值