Collections.sort,Enum,Comparable Interface问题

时间:2012-05-09 00:29:47

标签: java enums comparable

我有一张卡片,其他卡片(纸牌游戏)继承了这张卡片。卡套装和号码存储在这样的枚举

public static enum Suit {
    CLUBS, DIAMONDS, HEARTS, SPADES
};

public static enum Rank {
    DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE
};

我的第一个问题是如何改变卡牌排名。在每个单独的类(纸牌游戏)中,从卡类继承,因为不同的纸牌游戏在不同的牌上具有不同程度的重要性。

我的第二个问题是使用可比接口。

所以我有这样的类卡:

public  class Card implements Comparable<Card> {

public Suit suit;
public Rank rank;


public Card(Rank ranker, Suit suiter) {

    rank = ranker;
    suit = suiter;
}


//Other Methods for rank and suit here. 


@Override
public int compareTo(Card o) {

    int rankCom = rank.compareTo(o.rank);
    return rankCom != 0 ? rankCom : suit.compareTo(o.suit);
}

}

我刚刚介绍了类似的界面,我不完全确定我的实现是对的。当我想使用collections.sort(cards_saver)整理我的卡片时出现问题。 cards_saver是我存储卡片的地方。所有这一切都很好。 collections.shuffle(cards_saver)也可以正常工作。我收集时所遇到的问题是:

Bound mismatch: The generic method sort(List<T>) of type Collections is not applicable for the arguments (List<Card>). The inferred type Card is not a valid substitute for the bounded parameter <T extends Comparable<? super T>>

我会把我拥有的所有额外代码都提出来......只是这太长了。如果我没有充分解释问题,请发表评论 - 我会尝试解释。

先谢谢

3 个答案:

答案 0 :(得分:4)

  

我的第一个问题是如何改变卡牌排名。在每个单独的类别(纸牌游戏)中,由于不同的纸牌游戏从卡类继承,因此在不同的卡片上具有不同程度的重要性。

您有两种方法:

  1. 由于您继承自Card,因此您只需覆盖compareTo即可采取相应的行为。
  2. 您可以查看Comparator界面,这样便于根据上下文重新定义对象的比较规则。
  3. 至于你得到的那个错误,它确实没有意义。问题可能在其他地方。

答案 1 :(得分:2)

我认为对于语法错误,您必须将Card声明为(是的,我同意这是一种奇怪的语法)

public  class Card implements Comparable<? extends Card>

然后你可以在子类中重写。但是,我发现这经常让人感到困惑。另外,从设计的角度来看,这些卡在Bridge,Hearts,Poker中都是相同的。可以说,没有BridgeCard和PokerCard子类。有一张卡,但有一个不同的游戏,游戏决定你如何比较卡。

为了更加清晰,并且,如果你相信我的设计论点,为了更好的设计,不要使用Comparable,而是实现一堆 Comparators 。例如类似的东西:

static Comparator<Card> LOWBALL_POKER_COMPARATOR = new Comparator<Card>() {

      @Override
      public int compare(Card o1, Card o2) {
         // Ace is LOW is lowball poker, other cards as usual
      }

};

static Comparator<Card> PINOCLE_COMPARATOR = new Comparator<Card>() {
      @Override
      public int compare(Card o1, Card o2) {
         // I haven't played pinocle in so long I forget the rules...
      }
};

请注意,枚举可以实现比较器,因此您可以在枚举中包含所有这些比较器。你正在玩的CardGame的特定实例/子类在启动时为该游戏选择适当的Enum / Comparator,然后你去...

答案 2 :(得分:0)

您的代码适用于我。我刚刚给Card添加了一个toString方法:

import java.util.*;

class Card implements Comparable<Card> {

    static enum Suit {
        CLUBS, DIAMONDS, HEARTS, SPADES
    }

    static enum Rank {
        DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE
    }

    public Suit suit;
    public Rank rank;

    public Card (Rank ranker, Suit suiter) {
        rank = ranker;
        suit = suiter;
    }

    @Override
    public int compareTo (Card o) {
        int rankCom = rank.compareTo(o.rank);
        return rankCom != 0 ? rankCom : suit.compareTo(o.suit);
    }

    public String toString () {
        return suit.toString () + "\t" + rank.toString (); 
    }
}

并且 - 只是为了方便起见,将Rank和Suit添加为Card的内部枚举,但只是将所有内容添加到一个文件中 - 它不应该影响排序。这是测试:

public class CardTest
{
    public static void main (String args[])
    {
        List <Card> lc = new ArrayList <Card> ();
        lc.add (new Card (Card.Rank.SIX, Card.Suit.CLUBS)); 
        lc.add (new Card (Card.Rank.TEN, Card.Suit.CLUBS)); 
        lc.add (new Card (Card.Rank.SIX, Card.Suit.HEARTS)); 
        lc.add (new Card (Card.Rank.ACE, Card.Suit.HEARTS)); 

        System.out.println (lc);
        Collections.sort (lc);
        System.out.println (lc);
    }
}

输出:

[CLUBS  SIX, CLUBS  TEN, HEARTS SIX, HEARTS ACE]
[CLUBS  SIX, HEARTS SIX, CLUBS  TEN, HEARTS ACE]

您的代码将是:

        lc.add (new Card (Rank.TEN, Suit.CLUBS)); 

代替。

如果你有不同的卡牌顺序,那么创建一个新的Card类可能是最简单的方法。考虑到Poker,Bridge,Rommee,Blackjack等之间的相似之处可能是过度工程。