Comparable和Comparator接口

1 Comparable接口

如果需要对一个对象数组进行排序,Java提供了两种比较实现的方式,其中之一是:对象所属的类必须实现Comparable接口。下面是Comparable接口的代码:

public interface Comparable<T> {
    public int compareTo(T o);
}

任何实现Comparable接口的类都需要包含comoaraTo方法。即用当前对象与o作比较,如果这个对象小于o则返回一个负整数;如果相等则返回0;否则返回正整数。下面看一个实现Comparable接口进行排序的实例:

import java.util.Arrays;

public class TestComparable {
    public static void main(String[] args) {
        Stu[] stus = new Stu[]{new Stu("HC", 25, "CS"), new Stu("HC", 24, "CS"), new Stu("DSC", 24, "CS"), new Stu("MXD", 24, "DQ")};
        for (Stu s : stus) {
            System.out.println(s);
        }
        Arrays.sort(stus);
        for (Stu s : stus) {
            System.out.println(s);
        }
    }
}

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

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getDept() {
        return dept;
    }

    public void setDept(String dept) {
        this.dept = dept;
    }

    @Override
    public String toString() {
        return "Stu{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", dept='" + dept + '\'' +
                '}';
    }

    @Override
    public int compareTo(Stu o) {
        if (!o.getDept().equals(this.dept))
            return o.getDept().compareTo(this.dept);
        else if (!o.getName().equals(this.name))
            return o.getName().compareTo(this.name);
        else
            return o.getAge() - this.age;
    }
}

2 Comparator接口

在上面对Stu类进行排序的过程中,Stu类实现了Comparable接口,并完成了比较规则的定义,但是这种规则写的太死,如果需要对Stu类进行另一种排序,需要修改Stu类的源代码。这个时候可以使用Java提供的第二种比较实现方法:实现Comparator接口创建一个比较器,利用public static <T> void sort(List<T> list,Comparator<? super T> )进行比较。

2.1 自定义比较类实现Comparator接口

下面看一个使用Comparator接口进行排序的例子:

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TestComparator {
    public static void main(String[] args) {
        List<Per> pers = new ArrayList<>();
        pers.add(new Per("HC", 25));
        pers.add(new Per("HC", 23));
        pers.add(new Per("HC", 21));
        pers.add(new Per("AC", 26));

        Collections.sort(pers, new Comp());
        for (Per p : pers) {
            System.out.println(p);
        }
    }
}

class Per {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Per{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

class Comp implements Comparator<Per> {
    @Override
    public int compare(Per o1, Per o2) {
        if (!o1.getName().equals(o2.getName()))
            return o1.getName().compareTo(o2.getName());
        else
            return o1.getAge() - o2.getAge();
    }
}

2.2 lambda表达式在Comparator接口中的使用

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TestComparator {
    public static void main(String[] args) {
        List<Per> pers = new ArrayList<>();
        pers.add(new Per("HC", 25));
        pers.add(new Per("HC", 23));
        pers.add(new Per("HC", 21));
        pers.add(new Per("AC", 26));

        Collections.sort(pers, Comparator.comparing(Per::getName).thenComparing(Per::getAge));
        for (Per p : pers) {
            System.out.println(p);
        }
    }
}

class Per {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Per{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

上述提到了Comparator接口中的几个静态方法:

    	public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }
        default <U extends Comparable<? super U>> Comparator<T> thenComparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        return thenComparing(comparing(keyExtractor));
    }

对需要比较的对象应用上述函数,然后返回的键进行比较。

2.3 匿名内部类排序

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class TestComparator {
    public static void main(String[] args) {
        List<Per> pers = new ArrayList<>();
        pers.add(new Per("HC", 25));
        pers.add(new Per("HC", 23));
        pers.add(new Per("HC", 21));
        pers.add(new Per("AC", 26));

        Collections.sort(pers, new Comparator<Per>() {
            @Override
            public int compare(Per o1, Per o2) {
                return o1.getAge() - o2.getAge();
            }
        });
        for (Per p : pers) {
            System.out.println(p);
        }
    }
}

class Per {
    private String name;
    private int age;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "Per{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}

3 Comparable和Comparator两个接口的区别

  • Comparable:强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。只能在类中实现compareTo()一次,不能经常修改类的代码实现自己想要的排序。实现此接口的对象列表(和数组)可以通过Collections.sort(和Arrays.sort)进行自动排序,对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
  • Comparator强行对某个对象进行整体排序。可以将Comparator 传递给sort方法(如Collections.sort或Arrays.sort),从而允许在排序顺序上实现精确控制。还可以使用Comparator来控制某些数据结构(如有序set或有序映射)的顺序,或者为那些没有自然顺序的对象collection提供排序。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

是聪聪黄吖

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值