Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

The PlayingCard.java code should look somewhat familiar. This is a completed ver

ID: 3589660 • Letter: T

Question

The PlayingCard.java code should look somewhat familiar. This is a completed version of the PlayingCard class that we've been working with for the past few weeks. Portions of this code are commented out - leave it commented out for a moment. Look over the code for SetTest3 and make sure you can read it. SetTest3 just creates a number of playing cards and sticks them into a TreeSet.

Once you understand the SetTest3 code, run it. You will get a run-time exception error. Read the error message and notice what it is telling you - "PlayingCard cannot be cast to java.lang.Comparable". This is part of how TreeSet operates. Remember - TreeSet stores elements in a data structure known as a binary tree, and the binary tree stores elements in sorted order. If you can't compare two things, you can't store them in a tree, and you can't use TreeSet.

Fortunately there is an easy way around this. Change the class definition of PlayingCard so that it implements Comparable<PlayingCard>. You will get a syntax error telling you that you must implement the abstract method compareTo. This has already been done for you - scroll down to the bottom of the code and uncomment the compareTo method found there, save the PlayingCard code and run SetTest3 again. The runtime error should have gone away and you should see a set of PlayingCards displayed to your screen.

Now change the type of the Set from a TreeSet to a HashSet and run SetTest3 again. How does this HashSet perform differently than the TreeSet? Does it look like it's working correctly? Note your answer to this in the comments at the top of SetTest3.

To get HashSet to work properly, objects being stored in a HashSet must have two methods from Object overriden properly. One of these is equals(), which you will notice is written and working in the PlayingCard class. The other is a method called hashCode(). When called, the hashCode() method should return an integer value that follows these rules:

The value must be the same if two objects are equal (so two "Queen of Hearts" cards should return the same value).

The value should be different when two objects are not equal (so a "Two of Clubs" and a "Queen of Hearts" should return different values).

The value should always return the same number for the same object

You need to write a working hashCode method for the PlayingCard class. For this particular assignment we can implement a very simple one. Two cards that are the same have the same String value returned from toString(). The String class already has a working hashCode method. We can simply get our value from toString(), call the hashCode method on that result, and return it as the hashCode for the PlayingCard class. Your hashChode method MUST have the following method signature:

@Override
public int hashCode()

Once you have a hashCode method working, run SetTest3 again. What is different about the performance of SetTest3 now that you have a working hashCode method in your object? Note the differences in the comments at the top of SetTest3. (You may need to comment out your now working hashCode method to run it again to remind yourself of what the output looked like before you implemented hashCode).

Now that you've seen what TreeSet and HashSet need to function properly, think back to the original code in SetTest.java in the first exercise. Did TreeSet and HashSet store elements in different orders, or were they the same (you may need to go back and run that code again to remind yourself). It's probably pretty obvious how compareTo is implemented for integer -- given the behavior of HashSet and TreeSet, how do you think hashCode is implemented for numeric data types like integers? Put your answer in the comments at the top of SetTest3.

Explanation / Answer

The answer is given below and the modified files as well. When testing TreeSet, the HashSet was replaced by TreeSet in SetTest3. The comments are also written in the top java doc after ============== . The comments include the observations made when making changes. The same is provided below.

Hope the answer helped. If it did, please don't forget to rate the answer. Thank you.

After modifying the PlayingCard class to implement Comparable<PlayingCard>
and overriding the compareTo() method, the runtime exception was gone and
the code produced the following output (sorted)
[2C, 2D, 2H, 2S, 3C, 3D, 3H, 3S, QH]

When the code was changed to make use of HashSet, the output produced was
[3S, 3C, 3H, QH, QH, QH, QH, QH, 2D, QH, QH, 2C, QH, QH, QH, 2H, 2S, 3D]
To get the code to work with HashSet, the PlayingCard class was made to
override hashCode() method from Object.

The following output was produced.
[3S, 3C, 2S, 2C, 3D, 2D, 3H, 2H, QH]

The elements are not sorted in Hashset

So both TreeSet and HashSet ensure that there are no duplicates. Hashset needs
hashCode() to be overridden. TreeSet in addition ensure the data is stored in
sorted order.

Numeric data type such as integers return their numberic value as hashCode.
This ensures that the hashCode of the number is unique.

==============

Modified files


/**
* PlayingCard
*
* A simple class framework used to demonstrate the design
* of Java classes.
*
* @author Jeremy Morris
* @version 20120910
*/
public class PlayingCard implements Comparable<PlayingCard>{
  
// TODO - Setup private variables here
private char suit;
private char value;
  
private String validSuits="CDHS";
private String validValues = "23456789XJQKA";
  
public PlayingCard(char suit, char value) {
// This constructor should create the playing card
// No Mutators in this class - once a card is created
// its values never change
this.suit=suit;
this.value=value;
if (!checkSuit()) this.suit='X';
if (!checkValue()) this.value='0';
}
  
  
private boolean checkSuit() {
int check = validSuits.indexOf(this.suit);
boolean result;
if (check>=0) {
result=true;
}
else {
result=false;
}
return result;
// return (check>=0);
}
  
public boolean checkValue() {
boolean result;
int check = validValues.indexOf(this.value);
if (check>=0){
result=true;
}
else {
result=false;
}
return result;
//return (check>=0 || Character.isDigit(this.value));
}
  
/*
* getSuit()
* Returns the suit of the playing card as a character
*
* @return the suit of the playing card
*/
public char getSuit() {
// TODO - Implement getSuit()
return suit;
}
  
/*
* getValue()
* Returns the value of the playing card as a character
*
* @return value of the playing card
*/
public char getValue() {
// TODO - implement getValue()
return value;
}
  
@Override
public String toString() {
String result="";
if (value == 'X' )
result=result+"10";
else
result=result+value;
return result+suit;
}
@Override
public boolean equals(Object obj) {
boolean result=true;
if (getClass() != obj.getClass()) {
result=false;
}
else {
PlayingCard pc2 = (PlayingCard) obj;
if (pc2.getSuit() != this.suit || pc2.getValue() != this.value){
result=false;
}
}
return result;
}
  
@Override
public int compareTo(PlayingCard arg0) {
int result=0;
int valIdx = validValues.indexOf(value);
int arg0Idx = validValues.indexOf(arg0.getValue());
if (equals(arg0)) {
result=0;
}
else if (valIdx<arg0Idx) {
result=-1;
}
else if (valIdx>arg0Idx) {
result=1;
}
else {
// The two values are equal
int suitIdx = validSuits.indexOf(suit);
int arg0Suit = validSuits.indexOf(arg0.getSuit());
if (suitIdx>arg0Suit) {
result=1;
}
else if (suitIdx<arg0Suit) {
result=-1;
}
else {
result=0;
}
}
return result;
}

//override the hashCode() method from Object to get the HashSet to work with PlayingCard class
@Override
public int hashCode() {
return toString().hashCode();
}
  
}

/**
* SetTest3.java
*
*
* @author Jeremy Morris
* @version 20120927
*
* Code to show some simple set operations.
* This creates a set and places some PlayingCard objects
* into the set, then displays the contents of the set.
*
* This code is intended to provide an example of how classes
* must be written in order to be stored in sets.
*
*
* ===============================
*
* After modifying the PlayingCard class to implement Comparable<PlayingCard>
* and overriding the compareTo() method, the runtime exception was gone and
* the code produced the following output (sorted)
* [2C, 2D, 2H, 2S, 3C, 3D, 3H, 3S, QH]
*
* When the code was changed to make use of HashSet, the output produced was
* [3S, 3C, 3H, QH, QH, QH, QH, QH, 2D, QH, QH, 2C, QH, QH, QH, 2H, 2S, 3D]
* To get the code to work with HashSet, the PlayingCard class was made to
* override hashCode() method from Object.
*
* The following output was produced.
* [3S, 3C, 2S, 2C, 3D, 2D, 3H, 2H, QH]
*
* The elements are not sorted in Hashset
*
* So both TreeSet and HashSet ensure that there are no duplicates. Hashset needs
* hashCode() to be overridden. TreeSet in addition ensure the data is stored in
* sorted order.
*
* Numeric data type such as integers return their numberic value as hashCode.
* This ensures that the hashCode of the number is unique.
*/


import java.util.*;

public class SetTest3 {

public static void main(String[] args) {
  
Set<PlayingCard> cardSet = new HashSet<PlayingCard>();
cardSet.add(new PlayingCard('H','2'));
cardSet.add(new PlayingCard('S','2'));
cardSet.add(new PlayingCard('C','2'));
cardSet.add(new PlayingCard('D','2'));
cardSet.add(new PlayingCard('H','3'));
cardSet.add(new PlayingCard('S','3'));
cardSet.add(new PlayingCard('C','3'));
cardSet.add(new PlayingCard('D','3'));
for (int i=0; i<10; i++) {
cardSet.add(new PlayingCard('H','Q'));
}
System.out.println(cardSet);
}

}

Hire Me For All Your Tutoring Needs
Integrity-first tutoring: clear explanations, guidance, and feedback.
Drop an Email at
drjack9650@gmail.com
Chat Now And Get Quote