繁体   English   中英

无法从ArrayList中删除对象

[英]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 ,因此实际上这只是一个引用比较,因此,如果nextCardcard是对完全相同的对象的引用,则仅进入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;
    }
}

假设RankSuit是枚举(对于引用相等检查来说, equals是适当的)。 您可能也想在Card构造函数中添加无效检查。

您的Card类实际上应该是一个enum ,它将在每个不同的卡与每个不同的Java对象之间强制一对一的关系。 然后,您将不需要实现equalshashCode并且实际上可以使用==代替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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM