Java对象平等

时间:2010-01-26 12:52:46

标签: java equality data-structures

两张卡片c1和c4似乎相等......但它们不是原因。我希望它们相等,以便在Set中只允许其中一个。 :|

import java.util.*;
class Card2
{
 private int value;
 private String type;

 public Card2(int v,String t)
 {
  value=v;
  type=t;
 }

 public int getValue()
 {
  return value;
 }

 public String getType()
 {
  return type;
 }

 public String toString()
 {
  return(type+" "+value);
 }

 public boolean equals(Object oo)
 {
  if(!(oo instanceof Card))
  return false;

  Card cc=(Card) oo;

  if(this.getValue()==cc.getValue() && this.getType().equals(cc.getType()))
  return true;
  else
  return false;
 }

 public int hashCode()
 {
  return value;
 }

 public static void main(String args[])
 {
  HashSet<Card> deck=new HashSet<Card>();

  Card c1=new Card(5,"Spade");

  Card c2=new Card(10,"Hearts");

  Card c3=c2; //Equal Ref card entity

  Card c4=new Card(5,"Spade");

  System.out.println(c1.equals(c4));

  deck.add(c1);
  deck.add(c2);
  deck.add(c4);
  deck.add(c3);

  for(Card cc:deck)
  System.out.println(cc);
 }
}

8 个答案:

答案 0 :(得分:5)

首先:您调用了您的班级Card2,但在任何地方都将其称为Card(包括equals()方法。此答案假定您替换Card2的所有实例与Card)。

如果卡的值和类型相同,则您定义equals()以返回true

c1的值为5,类型为Spade

c4的值为5,类型为Spade

对我来说几乎一样。

答案 1 :(得分:2)

它们是相同的(一旦你通过Card2替换Card来解决拼写错误),你的程序输出是:

true
Hearts 10
Spade 5

您还期待什么?

答案 2 :(得分:1)

您的hashCode()equals()不一致。

java.util.HashSet使用hashCode。您应该实施hashCode()以考虑类型。

答案 3 :(得分:1)

有什么问题?我系统的输出是:

true
Spade 5
Hearts 10

这似乎正是你想要的。

答案 4 :(得分:1)

你的equals()方法错了,试试这个:

public boolean equals(Object oo)
{
  if(!(oo instanceof Card2))
    return false;

  Card2 cc=(Card2) oo;

  return this.getValue()==cc.getValue() && this.getType().equals(cc.getType());
}

也就是说,您应该对卡和卡2的使用保持一致。

另请注意,我更改了您的信息:

if(this.getValue()==cc.getValue() && this.getType().equals(cc.getType()))
  return true;
else
  return false;

return this.getValue()==cc.getValue() && this.getType().equals(cc.getType());

因为这个更短,并且避免违反checkstyle rule。这是一个好主意的原因是它使代码变得复杂,因为你所说的是“如果某些东西是真的,则返回true,否则如果它是假的,则返回false”。而不是强迫代码的读者解决你正在做的事情,你可以简单地说“返回一些东西”,代码的最终用户可以更快地理解你在做什么。

答案 5 :(得分:0)

您的equals()方法中缺少另一个等式检查。检查对象本身是否是相同的引用。当你比较像“c2.equals(c3)”这样的东西时,这是一个短路。

public boolean equals(Object oo)
{
  if(!(oo instanceof Card2))
    return false;

  if(this == oo) //comparing an object to itself is equal
    return true;

  Card2 cc=(Card2) oo;

  return this.getValue()==cc.getValue() && this.getType().equals(cc.getType());
}

答案 6 :(得分:0)

您的equals方法需要一些改进。您应该测试null和相同性。此外,如果允许子类化并在两个类中实现equals,则使用instanceof可能会导致equals变为非可交换。例如,如果Card2扩展了Card,而Card有一个等于测试例如Card的卡,而Card2用等于测试例如Card2的等于,那么对于一个实例cc2的类Card2和另一个实例cc的卡,使用instanceof意味着cc.equals(cc2)为真,但cc2.equals(cc)为false,可能导致不良行为。

您可以执行以下操作:

public boolean equals(Object other) {
    // null is not equal
    if (null == other)
        return false;
    // same is equal
    if (this == other)
        return true;
    // different class, not equal
    if (other.getClass() != getClass())
        return false;

或者,如果要允许子类化,则应仅测试超类中的属性。因此,如果Card有价值,而Card2扩展了Card并且有值和类型,那么你的equals方法应该只查找cardof instance并仅比较Card的属性:

    //if (other.getClass() != getClass())
    //    return false;
    if (!(other instanceof Card))
        return false;
    card = (Card) other;
    if (this.getValue() == card.getValue())
        return true;
    return false;
} 

然后,所有这些可能与您的问题完全无关。

答案 7 :(得分:0)

这是我们最近收到的一个项目中受欢迎的Card类;希望它会帮助你。 http://pastebin.com/qW41nwRE
“状态”用于确定卡是否在牌组,手牌等中。值为1到14,其中11 - 14是面牌(Jack,Queen,King和Ace)。