I'm having this problem where if I add a "new Card('A','S')" object into an ArrayList, I cannot remove it using remove(Obj o) from the ArrayList class, whether o is a Card object or a "new Card('A','S')" object.
It's strange because I've implemented comparable for my Card class and equality by compareTo() gives 0 while equals() gives true. I've also tested the equals() method it works with both comparing a Card object and a "new Card()" object.
If I add a Card object into the ArrayList however, I can remove it using a Card object but cannot remove it using "new Card('A','S')".
The output is as follows:Code:import java.util.ArrayList; public class Main { public static void main(String[] args) { ArrayList<Card> cardList = new ArrayList<Card>(); Card b = new Card('A', 'S'); cardList.add(new Card('A', 'S')); sop(cardList.toString()); sop(cardList.get(0).equals(new Card('A', 'S'))); sop(cardList.get(0).equals(b)); sop(new Card('A', 'S').equals(cardList.get(0))); sop(cardList.get(0).equals(b)); cardList.remove(new Card('A', 'S')); sop(cardList.toString()); cardList.remove(b); sop(cardList.toString()); cardList = new ArrayList<Card>(); cardList.add(b); sop(cardList.toString()); cardList.remove(b); sop(cardList.toString()); cardList.add(b); sop(cardList.toString()); cardList.remove(new Card('A', 'S')); sop(cardList.toString()); // ArrayList<String> a = new ArrayList<String>(); // String b = new String("apple"); // // a.add("apple"); // sop(a.toString()); // // a.remove("apple"); // sop(a.toString()); } public static void sop(Object obj) { System.out.println(obj.toString()); } }Interestingly, it doesn't affect String.Code:[AS] true true true true [AS] [AS] [AS] [] [AS] [AS]
I'm quite frustrated with this and any help would be much appreciated. I've no idea why this doesn't work yet equality test returns true. I could always run loops to remove elements using the remove(index i) method as it works but it's just avoiding the problem. Looking at the source for ArrayList doesn't offer me any hints about why this doesn't work.
Here's the source for Card in case it could help:
Code:/** * A Card consists of its Rank and Suit which cannot be changed. * @author chunkit */ public class Card implements Comparable<Card> { /** * Enumeration of rank of a card. * Each Rank contains a value for comparison and a char representation. */ public enum Rank { /** * Enum of three */ THREE(0, '3'), /** * Enum of four */ FOUR(1, '4'), /** * Enum of five */ FIVE(2, '5'), /** * Enum of six */ SIX(3, '6'), /** * Enum of seven */ SEVEN(4, '7'), /** * Enum of eight */ EIGHT(5, '8'), /** * Enum of nine */ NINE(6, '9'), /** * Enum of ten */ TEN(7, 'T'), /** * Enum of jack */ JACK(8, 'J'), /** * Enum of queen */ QUEEN(9, 'Q'), /** * Enum of king */ KING(10, 'K'), /** * Enum of ace */ ACE(11, 'A'), /** * Enum of two */ TWO(12, '2'); /** * Value a Rank represents for comparison purposes. */ private int value; /** * String representation of a Rank. */ private char representationOfRank; //representation of rank /** * Class constructor. * * @param value value a Rank represents for comparison purposes. * @param representationOfRank string representation of a Rank. */ private Rank(int value, char representationOfRank) { this.value = value; this.representationOfRank = representationOfRank; } /** * Returns char representation of a Rank. * @return char representation of a Rank. */ public char representationOfRank() { return representationOfRank; } /** * Returns value of a Rank for comparison purposes.<!-- --> Values are * consistent with order in which they are declared. * @return value of a Rank for comparison purposes. */ public int value() { return value; } } /** * Enumeration of suit of a card. * Each Suit contains a value for comparison and a char representation. */ public enum Suit { /** * Enum of diamonds */ DIAMONDS(0, 'D'), /** * Enum of clubs */ CLUBS(1, 'C'), /** * Enum of hearts */ HEARTS(2, 'H'), /** * Enum of spades */ SPADES(3, 'S'); /** * Value a Suit represents for comparison purposes. */ private int value; /** * String representation of a Suit. */ private char representationOfSuit; /** * Class constructor. * * @param value value a Suit represents for comparison purposes. * @param representationOfSuit string representation of a Suit. */ private Suit(int value, char representationOfSuit) { this.value = value; this.representationOfSuit = representationOfSuit; } /** * Returns char representation of a Suit. * @return char representation of a Suit. */ public char representationOfSuit() { return representationOfSuit; } /** * Returns value of a Suit for comparison purposes.<!-- --> Values are * consistent with order in which they are declared. * @return value of a Suit for comparison purposes. */ public int value() { return value; } } /** * Rank of a Card. */ private final Rank rank; /** * Suit of a Card. */ private final Suit suit; /** * Class constructor specifying the rank and suit using enum type. * * @param rank enum of Rank. * @param suit enum of Suit. */ public Card(Rank rank, Suit suit) { this.rank = rank; this.suit = suit; } /** * Class constructor specifying the rank and suit using char type. * * @param rank rank in char. * @param suit suit in char. */ public Card(char rank, char suit) { Rank theRank = null; Suit theSuit = null; for (Card.Rank rank2 : Card.Rank.values()) { if (rank == rank2.representationOfRank()) { theRank = rank2; break; } } for (Card.Suit suit2 : Card.Suit.values()) { if (suit == suit2.representationOfSuit()) { theSuit = suit2; break; } } this.rank = theRank; this.suit = theSuit; } // Note: 2 is larger than A. // But flush of 2,3,4,5,6 is smaller than A,2,3,4,5. So implement flush // comparator with care. // Perhaps we want to simplify this rule of Big Two. /** * Compares this card with the specified card for order. Returns a * negative integer, zero, or a positive integer as this card is less * than, equal to, or greater than the specified card. Cards are ordered by * value, followed by suit, as per Big Two rules. Has natural ordering and * consistent with equals. * * @param card the card to be compared. * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. */ public final int compareTo(Card card) { //Card other = (Card) card; //Card self = this; return (this.rank().value() * 4 + this.suit().value()) - (card.rank().value() * 4 + card.suit().value()); } /** * Compares the specified card with this card for equality. * * @param card a Card object. * @return true if the cards have the same rank and suit; false otherwise. */ public boolean equals(Card card) { if (this.compareTo(card) == 0) { return true; } else { return false; } } /** * Returns the rank of a card. * * @return the rank of a card. * @see Rank */ public Rank rank() { return rank; } /** * Returns the suit of a card. * * @return the suit of a card. * @see Suit */ public Suit suit() { return suit; } /** * Returns the condensed string representation of a Card.<!-- --> e.g.<!-- --> 3D, AS. * * @return the card in condensed string representation. */ @Override public String toString() { return rank.representationOfRank + "" + suit.representationOfSuit; } /** * Returns the full string representation of a Card.<!-- --> e.g.<!-- --> THREE of DIAMONDS, * ACE of SPADES. * * @return the card in full string representation. */ public String toStringLong() { return rank + " of " + suit; } }
There are currently 1 users browsing this thread. (0 members and 1 guests)
Bookmarks