3

カードゲームに取り組んでいます。何があっても、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;

}

私はすべてを試しましたが、削除されません。任意のヒント?

4

5 に答える 5

6

コレクションを繰り返し処理している場合、アイテムを削除する唯一removeの方法は、反復子を呼び出すことです。したがって、次を使用する必要があります。

if (nextCard.equals(card)) {
    it.remove();
    System.out.println("removed " + card);
}

equalsをオーバーライドしていないため、これは実際には参照比較にすぎないことに注意してください。そのため、ifステートメントの本文に入るのは、nextCardcardがまったく同じオブジェクトへの参照である場合のみです。

もちろん、メソッドでカードを削除するだけの場合は、次のように変更できます。

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これは、 andが列挙型であることを前提としてSuitいます (参照等価チェックインequalsが適切であるために)。おそらく、Cardコンストラクターにも nullity チェックを追加する必要があります。

于 2012-08-18T12:14:19.903 に答える
3

オブジェクトがコレクションで使用されている場合は、 と をオーバーライドすることを常にお勧めし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);
        }
    }
于 2012-08-18T12:14:47.330 に答える
2

クラスCardは実際にはenumである必要があります。これにより、個別のカードと個別の Java オブジェクトの間に 1 対 1 の関係が強制されます。equalsその後、 andを実装する必要はなくhashCode、実際には==の代わりに使用できequalsます。Card列挙型で定数を使用したり、非常に効率的なものを採用したり、さらに多くのことを行うことができますEnumSet。自分に好意を持ってくださいenum Card

于 2012-08-18T12:29:38.573 に答える
0

public メソッドは、記述する前にコメントしてください。コメントであなたの意図を示してください。それは今私を助けるでしょう。

誰かが前に述べたように、イテレータを使用してカードを削除する必要があります。

equals メソッドはあまり使用されていません。Card クラスの equal() メソッドをオーバーライドしていないため、Object クラスの equals() メソッドが呼び出されます。この equals メソッドは、Card インスタンスが同じ場合にのみ true を返します! これは equals() 仕様の非常に特殊なケースです。それはあなたの意図ですか?はいの場合、次のように書くとより明確になります。

if (nextCard == otherCard){..

equal 通常は次のことを意味します。

他のオブジェクトがこのオブジェクトと「等しい」かどうかを示します。

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

真実。これは推移的です: null 以外の参照値 x、y、および z に対して、x.equals(y) が true を返し、y.equals(z) が true を返す場合、x.equals(z) は true を返す必要があります。一貫性があります。null 以外の参照値 x および y に対して、x.equals(y) の複数の呼び出しは一貫して true を返すか、一貫して false を返します。ただし、オブジェクトの equals 比較で使用される情報が変更されていない場合に限ります。null 以外の参照値 x の場合、x.equals(null) は false を返す必要があります。

ソース: http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#equals%28java.lang.Object%29

remove メソッドが機能しないという結論に達したのはなぜですか?

以前に Iterator を使用していた場合は、使用すべきではない ArrayList() の remove メソッドを使用します。しかし、ArrayList() の remove メソッドには利点があります。つまり、ブール値を返します。常に戻り値をチェックしてください!あなたの場合、カードは常に削除する必要があり、メソッドはパブリックであるため、戻り値が false の場合は例外をスローする必要があります。(remove() を呼び出す前に carddeck を空にすることはできますか?)

remove メソッドを確認するもう 1 つの方法は、ArrayList のサイズが減少したかどうかを確認することです。

于 2012-08-18T15:02:58.527 に答える
0

まず、コンテナーを繰り返し処理しているときに何かを削除することはお勧めできません。次に、equals()メソッドを実装する必要があります。メソッドも実装すると、独自のメソッドを作成する代わりに、の組み込みメソッドhashCode()を使用できるようになります。ArrayListremove()

于 2012-08-18T12:13:43.527 に答える