[重学Java基础][类与接口][Part.1]Comparable接口与Comparator比较器类

[重学Java基础][类与接口][Part.1]Comparable接口与Comparator比较器类

前言

Java中有许多类都带有比较或者排序功能
例如Java 8 后在List的接口中添加的默认方法sort

default void sort(Comparator

Comparable 可比较接口

源码很简单 只有一个比较方法compareTo(T o)

public interface Comparable<T> {

    public int compareTo(T o);
}

Comparable对实现它的每个类的对象进行整体排序。这个接口需要类本身去实现
若一个类实现了Comparable 接口,则许多调用排序的方法可以不用显示的指定比较器
会默认调用类已经实现的比较接口的比较法则

public class Staff implements Comparable<Staff> {

    private Integer age;

    private String name;

    private String id;

    private String depart;

    private Integer level;
    ……
    @Override
    public int compareTo(Staff o) {
        if(this==o)
        {
            return 0;
        }
        if (this.level > o.level) {
            return 1;
        } else if (this.level < o.level) {
            return -1;
        }
        else {
          return 0;
        }
    }
}

Staff 类实现了Comparable接口 实现了compareTo方法

注意 Java 8后 升级了排序比较算法
比较处理法则 必须满足 大于返回正数 小于返回负数 等于返回0
不能再仅有大于和小于两种情况的处理结果

因此staff类可以被排序

   Staff[] staffs=……

   Arrays.sort(staffs);

测试代码

        Staff lilith=new Staff();

        lilith.setName("LilithBristol");
        lilith.setAge(18);
        lilith.setLevel(3);
        Staff Jolieye=new Staff();
        Jolieye.setName("JolieyeSigtuna");
        Jolieye.setAge(17);
        Jolieye.setLevel(2);

        List<Staff> staffList=new ArrayList<>(5);
        staffList.add(lilith);
        staffList.add(Jolieye);

        System.out.println(staffList);
        Collections.sort(staffList);

        System.out.println(staffList);

结果

[Staff{age=18, name='LilithBristol', id='null', depart='null', level=3}, Staff{age=17, name='JolieyeSigtuna', id='null', depart='null', level=2}]
[Staff{age=17, name='JolieyeSigtuna', id='null', depart='null', level=2}, Staff{age=18, name='LilithBristol', id='null', depart='null', level=3}]

 在《Effective Java》中,作者就推荐在编写自己的类的时候 尽可能的实现Comparable接口,因为如果实现了Comparable接口,就可以调用许多依赖此接口的泛型方法和工具类,只有很小的开销却获得了十分强大的功能。
  因此,所有Java平台类库中的存储数据结构都实现了Comparable接口。如果你自定义的类具有非常明显的内在排序关系,比如按字母顺序、按数值顺序或者,那你就应该考虑实现这个接口。

Comparator比较器

对于一个已存在的不能活或者不好变更的类 你也想要进行比较的情况
一个类已经有了默认的比较法则 而你需要一个不同的比较方式的情况
可以使用比较器 Comparator

public interface Comparator

相比Comparable接口 Comparator比较器的源码可就复杂多了
但细看后发现 增加的大部分是Java8 默认方法 用于处理流中的比较

    int compare(T var1, T var2);

    boolean equals(Object var1);

    default Comparator<T> reversed() {
        return Collections.reverseOrder(this);
    }

    default Comparator<T> thenComparing(Comparator<? super T> other) {
        Objects.requireNonNull(other);
        return (Comparator)((Serializable)((c1, c2) -> {
            int res = this.compare(c1, c2);
            return res != 0 ? res : other.compare(c1, c2);
        }));
    }

    default <U> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) {
        return this.thenComparing(comparing(keyExtractor, keyComparator));
    }

    default <U extends Comparable<? super U>> Comparator<T> thenComparing(Function<? super T, ? extends U> keyExtractor) {
        return this.thenComparing(comparing(keyExtractor));
    }

    default Comparator<T> thenComparingInt(ToIntFunction<? super T> keyExtractor) {
        return this.thenComparing(comparingInt(keyExtractor));
    }

    default Comparator<T> thenComparingLong(ToLongFunction<? super T> keyExtractor) {
        return this.thenComparing(comparingLong(keyExtractor));
    }

    default Comparator<T> thenComparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        return this.thenComparing(comparingDouble(keyExtractor));
    }

    static <T extends Comparable<? super T>> Comparator<T> reverseOrder() {
        return Collections.reverseOrder();
    }

    static <T extends Comparable<? super T>> Comparator<T> naturalOrder() {
        return NaturalOrderComparator.INSTANCE;
    }

    static <T> Comparator<T> nullsFirst(Comparator<? super T> comparator) {
        return new NullComparator(true, comparator);
    }

    static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
        return new NullComparator(false, comparator);
    }

    static <T, U> Comparator<T> comparing(Function<? super T, ? extends U> keyExtractor, Comparator<? super U> keyComparator) {
        Objects.requireNonNull(keyExtractor);
        Objects.requireNonNull(keyComparator);
        return (Comparator)((Serializable)((c1, c2) -> {
            return keyComparator.compare(keyExtractor.apply(c1), keyExtractor.apply(c2));
        }));
    }

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

    static <T> Comparator<T> comparingInt(ToIntFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator)((Serializable)((c1, c2) -> {
            return Integer.compare(keyExtractor.applyAsInt(c1), keyExtractor.applyAsInt(c2));
        }));
    }

    static <T> Comparator<T> comparingLong(ToLongFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator)((Serializable)((c1, c2) -> {
            return Long.compare(keyExtractor.applyAsLong(c1), keyExtractor.applyAsLong(c2));
        }));
    }

    static <T> Comparator<T> comparingDouble(ToDoubleFunction<? super T> keyExtractor) {
        Objects.requireNonNull(keyExtractor);
        return (Comparator)((Serializable)((c1, c2) -> {
            return Double.compare(keyExtractor.applyAsDouble(c1), keyExtractor.applyAsDouble(c2));
        }));
    }

使用比较器 普通情况下只需重写int compare(T var1, T var2)方法即可

        Staff lilith=new Staff();

        lilith.setName("LilithBristol");
        lilith.setAge(18);
        lilith.setLevel(3);
        Staff Jolieye=new Staff();
        Jolieye.setName("JolieyeSigtuna");
        Jolieye.setAge(17);
        Jolieye.setLevel(2);

        Staff tuzi=new Staff();
        tuzi.setName("tuzi");
        tuzi.setAge(28);

        List<Staff> staffList=new ArrayList<>(5);
        staffList.add(lilith);
        staffList.add(Jolieye);
        staffList.add(tuzi);

        System.out.println(staffList);
        Collections.sort(staffList,new Comparator<Staff>() {
              @Override
              public int compare(Staff o1, Staff o2) {
              if (x == y) {
              return 0;
                    }
              if (x.getAge() > y.getAge()) {
              return 1;
                    } else if (x.getAge().equals(y.getAge())) {
              return 0;
                    }else {
              return -1;
                    }
             }
        });

        System.out.println(staffList);

结果

[Staff{age=18, name='LilithBristol', id='null', depart='null', level=3}, Staff{age=17, name='JolieyeSigtuna', id='null', depart='null', level=2}, Staff{age=28, name='tuzi', id='null', depart='null', level=null}]
[Staff{age=17, name='JolieyeSigtuna', id='null', depart='null', level=2}, Staff{age=18, name='LilithBristol', id='null', depart='null', level=3}, Staff{age=28, name='tuzi', id='null', depart='null', level=null}]

此处就使用了比较器Comparator 传入了一种完全不同的比较法则

总结

Comparable 是比较接口,调用时必须继承接口,和一个具体类相绑定,
而Comparator 比较灵活,它可以被用于各个需要比较功能的类使用。
可以说前者属于静态绑定,而后者可以动态设定。
也可以把 Comparable 称为 “内部比较器”,而 Comparator 称为 “外部比较器”。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值