CSC 205 Java Programming II 2/8/2016 Lab 13 Using Java Collection API After this lab, you should be: Able to use methods of the java.util.Collections class to perform sort, shuffle, and swap operations on list objects Familiar with several Java interfaces such as Iterator, Comparable, and Comparator Able to use TreeMap and TreeSet to store collections of objects Part 1 – Manipulating Lists Using The java.util.Collections Class The java.util.Collections class provides a number of static methods that can be used to manipulate a List object: public static void shuffle(List list) Randomly permutes the specified list using a default source of randomness. public static void sort(List list) Sorts the specified list into ascending order, according to the natural ordering of its elements. public static void sort(List list, Comparator c) Sorts the specified list according to the order induced by the specified comparator. public static void swap(List list, int i, int j) Swaps the elements at the specified positions in the specified list. We will use a few simple applications to demonstrate how these methods can be used in simulating card games. The Card class, which is similar to the one introduced in King’s text is used extensively in the following tasks. 1.1 Sample code: DeckTest.java. This program intends to generate a deck of cards and then shuffle it into a random order. Notice that this class and the Card class belong to the card package. a. Compile and run this program. The order of cards in the deck doesn’t change after the dummy shuffle method is invoked. b. Implement the shuffle method by using the shuffle method of the Collections class as follows Collections.shuffle(cards); Compile and run the program to see the order change. c. Implement another shuffle method by using the swap method of the Collections class. The new method will take an int value as parameter, which specifies the desired number of swap operations. Add the following statements to the new method int i = Card.randomInt(0, cards.size()-1); int j = Card.randomInt(0, cards.size()-1); Collections.swap(cards, i, j); Lab 13-1 CSC 205 Java Programming II 2/8/2016 Modify the DeckTest program to invoke shuffle(10) (instead of simply shuffle()). Compile and run the program again to see what happens to the originally well ordered deck. Attach system output for each step as described above. 1.2 Sample code: HandTest.java. This program generates and then shuffles a deck of cards. The cards are then dealt to four players in a bridge game each has a Hand of cards. The Hand class, which contains up to 13 cards, belongs to the card.bridge package. This class provides a sort method that will be implemented below. a. Compile and run the HandTest.java program to see the dummy sort method cannot change the order of cards in a Hand object. b. Add the following statement to the sort method and execute again. Collections.sort(cards); The effect is that each hand of cards is sorted into the ascending order. In bridge, two cards in the same suit can be compared by rank, with 2 and ace as the lowest and highest, respectively. Suits are ranked from lowest to highest as: clubs, diamonds, hearts, and spades. The logic is implemented in the compareTo method in the Card class, which implements the Comparable interface. c. In bridge literature, hands are usually sorted in the descending order: that is spades will be listed first, and then hearts, diamonds, and clubs; in each suit, cards are listed from ace to 2. Another sort method of the Collections class that needs a Comparator object as parameter can sort cards in the order as defined in the Comparator object. Belonging to the java.util package, Comparable is an interface that requires a compare method. Read Java online APIs at java.sun.com/javase/6/docs/api/ to compare the two interfaces. Replace the statement you used for part b with the following code segment to see what happens to the sorted hands. Attach system output for each step as described above. 1.3 Follow suit. Read the method with the following header to see what the method intends to do. public Card pickCard(int suit) Pay special attention to see how the iterator object is used. (Iterator is an interface in the java.util package.) Part 2 – Providing A BridgeHand Class Using TreeSet and TreeMap The Hand class as described above provides a number of operations that a card game program can use to manipulate Card objects. But it is not easy to retrieve cards by suit and keep cards in always sorted by suit and then by rank, which is critical in a card game such as bridge. Now let’s provide a BridgeHand class to address these issues. This new class will use a TreeMap to manage suits: each Map.Entry contains a suit name (key) and the corresponding collection of cards (value). The value collection is organized with a TreeSet since there are no duplicate cards and the cards are ordered. Lab 13-2 CSC 205 Java Programming II 2/8/2016 2.1 First, let’s write a new BridgeHand class (in the card package) and declare the cards collection. How to take the advantage of Java generics? It makes the declaration more complicated but much safer and easier to implement. It should read private TreeMap<Integer, TreeSet<Card>> cards; A no-args version constructor that instantiates a blank TreeMap will also be needed. The following variable from the Card class is also helpful and can be added. private static final String suits = "CDHS"; 2.2 Let’s then implement the insertCard method and the toString method so that we can do some simple testing. The insertCard method will need to check if the suit is already in the map: if it is not there, instantiate a TreeSet suit, add the card in suit, and then add suit into the TreeMap; otherwise, retrieve the existing TreeSet as suit, add the card into the suit, and then add suit back into the TreeMap. The toString method needs to generate a String representation of the hand of card in the following format: C: D: H: S: 2 4 9 J A 5 9 J Q A T J Q 2.3 Now let’s implement the randomPick method that removes a card at random. This takes two steps: pick a suit that (still) exists and pick a card from it. Pick a suit can be achieved by randomly pick a suit label from the constant suits, and check to make sure it is in the map. With the suit label, you can retrieve the value as a TreeSet. We can use another loop to randomly pick a rank that exists in the set. Or for simplicity, you may remove the lowest ranking card by using thisSuit.remove(thisSuit.first()); 2.4 Next, let’s implement the pickCard(int suit) method that removes a card in a given suit. If there is no card (left) in the given suit (i.e., size of suit is zero), the randomPick method can be invoked to return any (remaining) card. Again, you can remove the lowest card in the given suit. 2.5 Lastly, let’s write a BridgeHandTest class (in the card package) similar to HandTest to test it out. Deliverables Your BridgeHandTest and BridgeHandTest classes and test scripts. Due by the beginning of our final session on Friday, Dec 14. Lab 13-3