代码之家  ›  专栏  ›  技术社区  ›  eddiewastaken

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

  •  1
  • eddiewastaken  · 技术社区  · 7 年前

    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;
    }
    

    使卡片类具有可比性,以便compareTo可用于按升序对卡片进行排序。

    @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;
            }
        }
    }
    

    添加一个比较器类作为名为CompareDescending的卡类的嵌套类。这应用于将卡片按降序排序。 我在这里做过,效果很好:

    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;
                }
            }
        }
    }
    

    然而,我想知道我是否走错了方向。我的嵌套比较器类是否应该在其内部使用compareTo()函数?这是更好的做法吗?

    2 回复  |  直到 7 年前
        1
  •  5
  •   Andreas dfa    7 年前

    compareTo 太复杂了。

    enum 实施 对于您,用于按声明的顺序(即按序号)对枚举值进行排序。

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

    要按相反顺序进行比较,只需翻转要比较的对象,即,而不是 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
        }
    }
    

    最好记录(注释)比较结果是相反的,因为随意查看代码可能很容易忽略这一点。在这里,我通过简单地评论比较是“下降”来记录它。

        2
  •  0
  •   Oleg Cherednik    7 年前

    Comparator 类提供适当的方法,使自定义比较器更容易。另外,, enum

    创造 降序 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 {}
    }
    

    演示

    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());