关于扑克游戏中 Card 对象的哈希码的建议?

发布于 2024-11-08 15:45:06 字数 33 浏览 1 评论 0原文

如何为由枚举花色和枚举等级组成的卡片对象计算哈希码?

How is the hashcode computed for a card object which consists of enum suit and enum rank ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

要走干脆点 2024-11-15 15:45:06

如果您使用 Eclipse,它可以为您生成一个“足够好”的 hashCode() 实现:

上下文菜单屏幕截图

public class Card
{
    private Suit suit;
    private Rank rank;

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((rank == null) ? 0 : rank.hashCode());
        result = prime * result + ((suit == null) ? 0 : suit.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj) return true;
        if (!(obj instanceof Card)) return false;
        Card other = (Card) obj;
        if (rank != other.rank) return false;
        if (suit != other.suit) return false;
        return true;
    }
}

我只能想象 NetBeans、IntelliJ IDEA 等也可以做到这一点。


也就是说,由于域很小,这个实现同样可以很好地工作(我认为......):

public int hashCode()
{
    int rankHash = ((rank == null) ? 0 : (1+rank.ordinal()));
    int suitHash = ((suit == null) ? 0 : (1+suit.ordinal()));
    return rankHash + 31*suitHash;
}

这假设 Rank 序数包含 0-12 并且 >Suit 序数包括 0-3。请注意,大部分丑陋的情况都来自空检查。如果这些值永远不能为空,那么:

public int hashCode()
{
    return rank.ordinal() + 31*suit.ordinal();
}

If you're using Eclipse, it can generate a "good enough" hashCode() implementation for you:

context menu screenshot

public class Card
{
    private Suit suit;
    private Rank rank;

    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((rank == null) ? 0 : rank.hashCode());
        result = prime * result + ((suit == null) ? 0 : suit.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj)
    {
        if (this == obj) return true;
        if (!(obj instanceof Card)) return false;
        Card other = (Card) obj;
        if (rank != other.rank) return false;
        if (suit != other.suit) return false;
        return true;
    }
}

I can only imagine that NetBeans, IntelliJ IDEA, etc., can do this as well.


That said, since the domain is small, this implementation will work equally well (I think...):

public int hashCode()
{
    int rankHash = ((rank == null) ? 0 : (1+rank.ordinal()));
    int suitHash = ((suit == null) ? 0 : (1+suit.ordinal()));
    return rankHash + 31*suitHash;
}

This assumes that Rank ordinals are 0-12 inclusive and Suit ordinals are 0-3 inclusive. Note that most of the ugliness there comes from the null checks. If the values can never be null, then:

public int hashCode()
{
    return rank.ordinal() + 31*suit.ordinal();
}
万水千山粽是情ミ 2024-11-15 15:45:06

由于值空间如此之小(是 13 乘以 4 吗?),为任何两张卡分配相同的哈希码是没有意义的。所以这完全取决于你,但类似这样的事情

A spades = 1
K spades = 2
....
A clubs = 21
K clubs = 22
....

应该没问题。

一般来说,如果确实存在大量可能的值(例如每个可能的 String 值或每个可能的数字列表 List),那么定义哈希码是有意义的将它们限制为(投影到)有限的哈希码值空间。如果我们讨论的是 java.lang.Object API 定义的 hashCode(),那么“哈希码值的有限空间”必须适合 int类型(整数)。

With so little value space (is it 13 times 4?) it makes no sense to assign any two cards the same hash-code. So it's completely up to you, but something like:

A spades = 1
K spades = 2
....
A clubs = 21
K clubs = 22
....

should be OK.

Generally it makes sense to define a hashcode if there are really huge numbers of possible values (like every possible String value or every possible list of numbers List<Number>) and to have them limited to (projected into) a limited space of hashcode values. If we are talking about hashCode() as defined by java.lang.Object API then the 'limited space of hashcode values' has to fit into int type (integers).

顾挽 2024-11-15 15:45:06

卡域 ( 52 ) 的空间足够小,足以容纳其自身的枚举。这也将为您提供一个用于识别的自然主键,因为 hashCode 也应该是对象内部状态的唯一标识符。

下面是一些伪 Java 代码,可以让您了解一下:

public enum Suit
    HEART, CLUB, SPADE, DIAMOND

public enum Rank
    TWO, THREE, FOUR ... KING, QUEEN, ACE

public enum Card
   private final Suit suit;
   private final Rank rank;
   private Card(final Suit s, final Rank r);

   ACE_HEARTS(ACE,HEART), TWO_HEARTS(TWO,HEART), ... KING_DIAMONDS(KING, DIAMOND);

   public int hashCode() { return this.ordinal; )

The space of the cards domain ( 52 ) is small enough to fit into an enum it self. And that would give you a natural primary key for identification as well, since hashCode should be a unique identifier for the internal state of the object as well.

Here is some pseudo Java code to give you an idea:

public enum Suit
    HEART, CLUB, SPADE, DIAMOND

public enum Rank
    TWO, THREE, FOUR ... KING, QUEEN, ACE

public enum Card
   private final Suit suit;
   private final Rank rank;
   private Card(final Suit s, final Rank r);

   ACE_HEARTS(ACE,HEART), TWO_HEARTS(TWO,HEART), ... KING_DIAMONDS(KING, DIAMOND);

   public int hashCode() { return this.ordinal; )
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文