118. Java 接口 – 接口功能增强实战默认方法、静态方法与Comparator链式排序策略

内容分享2周前发布
0 0 0

118. Java 接口 – 接口功能增强实战默认方法、静态方法与Comparator链式排序策略

默认方法(default methods)使得可以为现有接口添加新功能,并且确保与旧版本接口兼容。通过使用默认方法,能够在不破坏旧版代码的情况下为接口添加新方法,甚至支持使用 lambda 表达式作为参数。这为库的扩展和版本兼容性提供了强劲的支持。

接下来,我们通过增强 Comparator 接口来展示如何使用默认方法和静态方法来实现更灵活的功能。

示例:扩展 Comparator 接口

假设我们有两个接口:CardDeckCard 接口定义了两种枚举类型 SuitRank,以及两个抽象方法 getSuit()getRank()

Card 接口

public interface Card extends Comparable<Card> {
    
    public enum Suit { 
        DIAMONDS(1, "Diamonds"), 
        CLUBS(2, "Clubs"), 
        HEARTS(3, "Hearts"), 
        SPADES(4, "Spades");
        
        private final int value;
        private final String text;
        Suit(int value, String text) {
            this.value = value;
            this.text = text;
        }
        public int value() { return value; }
        public String text() { return text; }
    }
    
    public enum Rank { 
        DEUCE(2, "Two"), 
        THREE(3, "Three"), 
        FOUR(4, "Four"), 
        FIVE(5, "Five"), 
        SIX(6, "Six"), 
        SEVEN(7, "Seven"), 
        EIGHT(8, "Eight"), 
        NINE(9, "Nine"), 
        TEN(10, "Ten"), 
        JACK(11, "Jack"), 
        QUEEN(12, "Queen"), 
        KING(13, "King"), 
        ACE(14, "Ace");
        
        private final int value;
        private final String text;
        Rank(int value, String text) {
            this.value = value;
            this.text = text;
        }
        public int value() { return value; }
        public String text() { return text; }
    }
    
    public Suit getSuit();
    public Rank getRank();
}

Deck 接口

Deck 接口定义了对卡片组的操作,包括排序、添加卡片、洗牌等方法。

public interface Deck {
    
    List<Card> getCards();
    Deck deckFactory();
    int size();
    void addCard(Card card);
    void addCards(List<Card> cards);
    void addDeck(Deck deck);
    void shuffle();
    void sort();
    void sort(Comparator<Card> c);
    String deckToString();

    Map<Integer, Deck> deal(int players, int numberOfCards)
        throws IllegalArgumentException;
}

PlayingCard

PlayingCard 类实现了 Card 接口,并提供了实现细节。

public class PlayingCard implements Card {

    private Rank rank;
    private Suit suit;

    // constructor

    @Override
    public Suit getSuit() {
        return this.suit;
    }

    @Override
    public Rank getRank() {
        return this.rank;
    }

    @Override
    public int compareTo(Card o) {
        return this.hashCode() - o.hashCode();
    }

    @Override
    public int hashCode() {
        return ((suit.value() - 1) * 13) + rank.value();
    }
}

StandardDeck

StandardDeck 类实现了 Deck 接口,并提供了排序功能。使用 Collections.sort() 方法对 Deck 进行排序。

public class StandardDeck implements Deck {

    private List<Card> entireDeck;

    // constructor, accessors

    @Override
    public void sort() {
        Collections.sort(entireDeck);
    }

    @Override
    public void sort(Comparator<Card> c) {
        Collections.sort(entireDeck, c);
    }
}

在此例中,compareTo() 方法在 PlayingCard 类中实现,用于按花色和等级对卡片进行排序。StandardDeck.sort() 方法默认按照 compareTo() 的规则对卡片进行排序。

按等级和花色排序

如果需要按等级排序,然后按花色排序,可以使用 Comparator 接口实现自定义排序规则:

public class SortByRankThenSuit implements Comparator<Card> {
    @Override
    public int compare(Card firstCard, Card secondCard) {
        int compVal = firstCard.getRank().value() - secondCard.getRank().value();
        if (compVal != 0)
            return compVal;
        else
            return firstCard.getSuit().value() - secondCard.getSuit().value();
    }
}

使用 ComparatorDeck 进行排序:

StandardDeck myDeck = new StandardDeck();
myDeck.shuffle();
myDeck.sort(new SortByRankThenSuit());

使用 Lambda 表达式简化排序

使用 lambda 表达式,可以简化排序逻辑,不必显式定义 Comparator 类。例如,按等级排序:

StandardDeck myDeck = new StandardDeck();
myDeck.shuffle();
myDeck.sort((firstCard, secondCard) ->
    firstCard.getRank().value() - secondCard.getRank().value()
);

增强 Comparator 接口:静态方法

Comparator 接口已经通过静态方法增强,允许您使用更简洁的方式定义排序规则。例如,按 CardRank 排序:

myDeck.sort(Comparator.comparing(Card::getRank));

这种方式允许您使用方法引用来简化代码。静态方法 Comparator.comparing() 提供了基于属性的比较功能。

链式排序:thenComparing()

Comparator 接口的默认方法 thenComparing() 可以让您将多个比较标准组合起来。例如,先按等级排序,再按花色排序:

myDeck.sort(
    Comparator
        .comparing(Card::getRank)
        .thenComparing(Card::getSuit)
);

反向排序:reversed()

如果需要对排序结果进行反转(例如按等级降序排序),Comparator 接口提供了 reversed() 方法:

myDeck.sort(
    Comparator.comparing(Card::getRank)
        .reversed()
        .thenComparing(Card::getSuit)
);

总结

  • 默认方法:通过向接口添加默认方法,您可以扩展现有接口的功能,而不会破坏旧版代码。
  • 静态方法Comparator 接口的静态方法使得排序更加简洁,并允许您使用 lambda 表达式或方法引用来创建比较器。
  • 链式排序thenComparing() 方法使您能够组合多个比较条件,增强了排序的灵活性。
  • 反向排序:通过 reversed() 方法,您可以轻松地对排序结果进行反转。

通过这些增强功能,可以创建更简洁、更灵活的排序逻辑,使得库的使用更加方便和易于理解。这些功能极大地提升了 Java 接口的表现力和可用性。

© 版权声明

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
none
暂无评论...