[英]Can't remove object from ArrayList
我正在玩纸牌游戏。 无论如何,我不知道如何从ArrayList中删除卡。 这是我正在使用的代码:
private List<Card> cardDeck = new ArrayList<Card>();
public void removeCard(Card card) {
for (Iterator<Card> it = cardDeck.iterator(); it.hasNext();) {
Card nextCard = it.next();
if (nextCard.equals(card)) {
cardDeck.remove(card);
System.out.println("removed " + card);
}
}
}
如果需要,这是卡类:
public class Card {
public Card(Rank rank, Suit suit) {
this.rank = rank;
this.suit = suit;
}
public Rank getRank() {
return rank;
}
public Suit getSuit() {
return suit;
}
@Override
public String toString() {
return getRank().toString().toLowerCase() + " of "
+ getSuit().toString().toLowerCase();
}
private Rank rank;
private Suit suit;
}
我已经尝试了所有方法,但不会将其删除。 有小费吗?
当您遍历集合时,要删除项目的唯一方法是在迭代器上调用remove
。 因此,您应该使用:
if (nextCard.equals(card)) {
it.remove();
System.out.println("removed " + card);
}
请注意,由于您尚未覆盖equals
,因此实际上这只是一个引用比较,因此,如果nextCard
和card
是对完全相同的对象的引用,则仅进入if
语句的主体。
当然,如果您只想删除卡的方法,则应该可以将其更改为:
public void removeCard(Card card) {
cardDeck.remove(card);
}
...当然,对平等也有同样的警告。
要覆盖equals
(和hashCode
以保持一致性),我首先将Card
为最终类,然后编写:
public final class Card {
...
@Override
public boolean equals(Object other) {
if (!(other instanceof Card)) {
return false;
}
Card otherCard = (Card) other;
return this.rank == otherCard.rank &&
this.suit == otherCard.suit;
}
@Override
public int hashCode() {
int hash = 17;
hash = hash * 31 + rank.hashCode();
hash = hash * 31 + suit.hashCode();
return hash;
}
}
假设Rank
和Suit
是枚举(对于引用相等检查来说, equals
是适当的)。 您可能也想在Card
构造函数中添加无效检查。
您的Card
类实际上应该是一个enum
,它将在每个不同的卡与每个不同的Java对象之间强制一对一的关系。 然后,您将不需要实现equals
和hashCode
并且实际上可以使用==
代替equals
。 您可以在枚举中使用Card
常量,使用非常有效的EnumSet
等。 帮个忙, enum Card
。
在集合中使用对象时,最好覆盖equals()
和hashcode()
。 否则,查找时相等条件可能会失败。
解决您的问题的另一种方法是:
使用it.remove()
代替cardDeck.remove(card);
例:
for (Iterator<Card> it = cardDeck.iterator(); it.hasNext();) {
Card nextCard = it.next();
if (nextCard.equals(card)) {
it.remove();
System.out.println("removed " + card);
}
}
首先,在容器上迭代时删除一些东西不是一个好主意。 其次,您必须实现equals()
方法。 如果您还实现hashCode()
方法,则可以使用ArrayList
的内置remove()
方法,而不必编写自己的方法。
在编写公共方法之前,先对其进行注释。 通过评论说明您的意图。 现在对我有帮助。
如前所述,您应该使用迭代器删除卡。
equals方法不能很好地使用。 由于尚未在Card类中重写equal()方法,因此将调用Object类的equals()方法。 如果Card实例相同,则equals方法仅返回true! 这是equals()规范的一种非常特殊的情况。 那是你的意图吗? 如果是,那么写起来会更清楚:
如果(nextCard == otherCard){。
平等通常意味着:
指示其他某个对象是否与此对象“相等”。
equals方法对非null对象引用实现对等关系:
It is reflexive: for any non-null reference value x, x.equals(x) should return true. It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns
真正。 它是可传递的:对于x,y和z的任何非空引用值,如果x.equals(y)返回true,而y.equals(z)返回true,则x.equals(z)应该返回true。 这是一致的:对于任何非空引用值x和y,只要未修改对象的equals比较中使用的信息,对x.equals(y)的多次调用将始终返回true或始终返回false。 对于任何非null参考值x,x.equals(null)应该返回false。
来源: http : //docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals%28java.lang.Object%29
您是如何得出删除方法无效的结论?
如果以前使用过Iterator,则应使用ArrayList()的remove方法,该方法不应该使用。 但是ArrayList()的remove方法有一个优点:它返回一个布尔值。 始终检查返回值! 我认为,因为在这种情况下,必须始终将卡取出,并且该方法是公共的,因此如果返回值为false,则应引发异常。 (在调用remove()之前,卡座是否为空?)
检查remove方法的另一种方法是检查ArrayList的大小是否减小。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.