简体   繁体   English

如何使用compareTo()实现比较器

[英]How to implement Comparator using compareTo()

I have a class, Card : 我有一堂课, Card

public class Card implements Comparable<Card> {
    public enum rank {TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE};
    private rank Rank;
    public enum suit {CLUBS, DIAMONDS, HEARTS, SPADES};
    private suit Suit;
}

Which I need to perform two tasks on. 我需要在上面执行两项任务。 First - Make the Card class Comparable, so that compareTo can be used to sort the cards into ascending order. 首先- 使Card类具有可比性,以便compareTo可以将卡片按升序排序。 I've done this here: 我已经在这里完成了:

@Override
public int compareTo(Card other) {
    if(this.Rank != other.Rank) {
        if(this.Rank.ordinal() > other.Rank.ordinal()) {
        return 1;
        }
        else if(this.Rank.ordinal() < other.Rank.ordinal()) {
            return -1;
        }
        else {
            return 0;
        }
    }
    else {
        if(this.Suit.ordinal() > other.Suit.ordinal()) {
        return 1;
        }
        else if(this.Suit.ordinal() < other.Suit.ordinal()) {
            return -1;
        }
        else {
            return 0;
        }
    }
}

and secondly - Add a Comparator class as a nested classes of the Card class called CompareDescending. 其次- 将Comparator类作为Card类的嵌套类(称为CompareDescending)添加。 This should be used to sort the cards into descending order. 这应该用于按降序对卡进行排序。 I've done this here, and it works well: 我已经在这里完成了,并且效果很好:

public static class CompareDescending implements Comparator<Card> {
    @Override
    public int compare(Card card, Card other) {
        if(card.Rank != other.Rank) {
            if(card.Rank.ordinal() < other.Rank.ordinal()) {
            return 1;
            }
            else if(card.Rank.ordinal() > other.Rank.ordinal()) {
                return -1;
            }
            else {
                return 0;
            }
        }
        else {
            if(card.Suit.ordinal() < other.Suit.ordinal()) {
            return 1;
            }
            else if(card.Suit.ordinal() > other.Suit.ordinal()) {
                return -1;
            }
            else {
                return 0;
            }
        }
    }
}

However, I wondered if I've gone about this the wrong way. 但是,我想知道我是否采用了错误的方式。 Should my nested Comparator class use the compareTo() function inside it? 我的嵌套Comparator类应该在其中使用compareTo()函数吗? Is this better practice? 这是更好的做法吗?

Your compareTo is overly complex. 您的compareTo过于复杂。

enum implements a compareTo for you, for ordering enum values in the declared order, ie by ordinal. enum为您实现一个compareTo ,用于以声明的顺序(即按序)对枚举值进行排序。

That means your code can simply be: 这意味着您的代码可以简单地是:

@Override
public int compareTo(Card other) {
    int cmp = this.Rank.compareTo(other.Rank);
    if (cmp == 0)
        cmp = this.Suit.compareTo(other.Suit);
    return cmp;
}

To compare in reverse order, you simply flip the objects being compared, ie instead of a.compareTo(b) you write b.compareTo(a) , so a descending Comparator implementation would be: 要以相反的顺序进行比较,您只需翻转要比较的对象,即编写b.compareTo(a)而不是a.compareTo(b) b.compareTo(a) ,那么降序的Comparator实现将是:

public static class CompareDescending implements Comparator<Card> {
    @Override
    public int compare(Card card, Card other) {
        return other.compareTo(card); // descending
    }
}

It is a good idea to document (comment) that the comparison is reversed, because casual review of the code might very easily miss that. 记录(注释)比较是一个好主意,因为对代码的随意检查可能很容易错过这一点。 Here, I have documented it by simply commenting that the compare is "descending". 在这里,我通过简单地评论比较是“下降的”来记录它。

You custom comparator is very complex. 您自定义的比较器非常复杂。 Comparator class provides suitable method to make custom comparator easier. Comparator类提供了合适的方法来简化自定义比较器。 Additionally, enum implements natural order comparator. 此外, enum实现自然顺序比较器。

To create descending order comparator you do not have to rewrite existed asceding order comparator. 要创建降序比较器,您不必重写现有的升序比较器。 Just call Comparator.reverseOrder() before. 只需在之前调用Comparator.reverseOrder()

class Card implements Comparable<Card> {

    public static final Comparator<Card> SORT_ASC = Comparator.<Card, Rank>comparing(card -> card.rank).thenComparing(card -> card.suit);
    public static final Comparator<Card> SORT_DESC = SORT_ASC.reversed();

    private Rank rank;
    private Suit suit;

    @Override
    public int compareTo(Card card) {
        return SORT_ASC.compare(this, card);
    }

    public enum Rank {}
    public enum Suit {}
}

Demo 演示版

List<Card> cards = Collections.emptyList();
List<Card> asc = cards.stream().sorted(Card.SORT_ASC).collect(Collectors.toList());
List<Card> desc = cards.stream().sorted(Card.SORT_DESC).collect(Collectors.toList());

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM