AhmadLang / Java, How To Program, 2004
.pdf
Line 37 calls Vector method indexOf to determine the index of the first location in the Vector that contains the argument. The method returns 1 if the argument is not found in the Vector. An overloaded version of this method takes a second argument specifying the index in the Vector at which the search should begin.
Performance Tip 19.6
Vector methods contains and indexOf perform linear searches of a Vector's contents. These searches are inefficient for large Vectors. If a program frequently searches for elements in a collection, consider using one of the Java Collection API's Map implementations (Section 19.10), which provide high-speed searching capabilities.
Line 41 calls Vector method remove to remove the first occurrence of its argument from the Vector. The method returns true if it finds the element in the Vector; otherwise, the method returns false. If the element is removed, all elements after that element in the Vector shift one position toward the beginning of the Vector to fill in the position of the removed element. Class Vector also provides method
removeAllElements to remove every element from a Vector and method removeElementAt to remove the element at a specified index.
Lines 5354 use Vector methods size and capacity to determine the number of elements currently in the Vector and the number of elements that can be stored in the Vector without allocating more memory, respectively.
Line 59 calls Vector method isEmpty to determine whether the Vector is empty. The method returns TRue if there are no elements in the Vector; otherwise, the method returns false. Lines 6667 use the enhanced for statement to print out all elements in the vector.
Among the methods introduced in Fig. 19.6, firstElement, lastElement and capacity can be used only with Vector. Other methods (e.g., add, contains, indexOf, remove, size and isEmpty) are declared by List, which means that they can be used by any class that implements List, such as Vector.
[Page 922 (continued)]
19.6. Collections Algorithms
The collections framework provides several high-performance algorithms for manipulating collection elements. These algorithms are implemented as static methods of class Collections (Fig. 19.7). Algorithms sort, binarySearch, reverse, shuffle, fill and copy operate on Lists. Algorithms min, max, addAll, frequency and disjoint operate on Collections.
|
[Page 923] |
|
Figure 19.7. Collections algorithms. |
Algorithm |
Description |
|
|
sort |
Sorts the elements of a List. |
binarySearch |
Locates an object in a List. |
reverse |
Reverses the elements of a List. |
shuffle |
Randomly orders a List's elements. |
fill |
Sets every List element to refer to a specified object. |
copy |
Copies references from one List into another. |
min |
Returns the smallest element in a Collection. |
max |
Returns the largest element in a Collection. |
addAll |
Appends all elements in an array to a collection. |
frequency |
Calculates how many elements in the collection are equal to the |
|
specified element. |
disjoint |
Determines whether two collections have no elements in |
|
common. |
|
|
Software Engineering Observation 19.4
The collections framework algorithms are polymorphic. That is, each algorithm can operate on objects that implement specific interfaces, regardless of the underlying implementations.
19.6.1. Algorithm sort
Algorithm sort sorts the elements of a List, which must implement the Comparable interface. The order is determined by the natural order of the elements' type as implemented by its class's compareTo method. Method compareTo is declared in interface Comparable and is sometimes called the natural comparison method. The sort call may specify as a second argument a Comparator object that determines an alternative ordering of the elements.
(This item is displayed on pages 924 - 925 in the print version)
1 // Fig. 19.9: Sort2.java
2 // Using a Comparator object with algorithm sort.
3import java.util.List;
4import java.util.Arrays;
5import java.util.Collections;
7public class Sort2
8{
9private static final String suits[] =
10{ "Hearts", "Diamonds", "Clubs", "Spades" };
12// output List elements
13public void printElements()
14{
15List list = Arrays.asList( suits ); // create List
17// output List elements
18System.out.printf( "Unsorted array elements:\n%s\n", list );
20// sort in descending order using a comparator
21Collections.sort( list, Collections.reverseOrder() );
23// output List elements
24System.out.printf( "Sorted list elements:\n%s\n", list );
25} // end method printElements
27public static void main( String args[] )
28{
29Sort2 sort2 = new Sort2();
30sort2.printElements();
31} // end main
32} // end class Sort2
Unsorted array elements:
[Hearts, Diamonds, Clubs, Spades] Sorted list elements:
[Spades, Hearts, Diamonds, Clubs]
[Page 925]
Sorting with a Comparator
Figure 19.10 creates a custom Comparator class, named TimeComparator, that implements interface Comparator to compare two Time2 objects. Class Time2, declared in Fig. 8.5, represents times with hours, minutes and seconds.
Figure 19.10. Custom Comparator class that compares two Time2 objects.
|
|
(This item is displayed on page 926 in the print version) |
1 |
// Fig. 19.10: TimeComparator.java |
|
2 |
// Custom Comparator class that compares two Time2 objects. |
|
3 |
import |
java.util.Comparator; |
4 |
|
|
5 |
public |
class TimeComparator implements Comparator< Time2 > |
6 |
{ |
|
7 public int compare( Time2 tim1, Time2 time2 )
8{
9int hourCompare = time1.getHour() - time2.getHour(); // compare hour
11// test the hour first
12if ( hourCompare != 0 )
13 |
return hourCompare; |
14 |
|
15int minuteCompare =
16time1.getMinute() - time2.getMinute(); // compare minute
18// then test the minute
19if ( minuteCompare != 0 )
20 |
return minuteCompare; |
21 |
|
22int secondCompare =
23time1.getSecond() - time2.getSecond(); // compare second
25return secondCompare; // return result of comparing seconds
26} // end method compare
27} // end class TimeComparator
Class TimeComparator implements interface Comparator, a generic type that takes one argument (in this case Time2). Method compare (lines 726) performs comparisons between Time2 objects. Line 9 compares the two hours of the Time2 objects. If the hours are different (line 12), then we return this value. If this value is positive, then the first hour is greater than the second and the first time is greater than the second. If this value is negative, then the first hour is less than the second and the first time is less than the second. If this value is zero, the hours are the same and we must test the minutes (and maybe the seconds) to determine which time is greater.
Figure 19.11 sorts a list using the custom Comparator class TimeComparator. Line 11 creates an ArrayList of Time2 objects. Recall that both ArrayList and List are generic types and accept a type argument that specifies the element type of the collection. Lines 1317 create five Time2 objects and add them to this list. Line 23 calls method sort, passing it an object of our TimeComparator class (Fig. 19.10).
Figure 19.11. Collections method sort with a custom Comparator object.
(This item is displayed on pages 926 - 927 in the print version)
1 // Fig. 19.11: Sort3.java
2 // Sort a list using the custom Comparator class TimeComparator.
3import java.util.List;
4import java.util.ArrayList;
5import java.util.Collections;
7public class Sort3
8{
9public void printElements()
10{
11 |
List< Time2 > |
list = |
new |
ArrayList< Time2 >(); // create List |
||||
12 |
|
|
|
|
|
|
|
|
13 |
list.add( |
new |
Time2( |
6 |
, |
24, 34 ) ); |
||
14 |
list.add( |
new |
Time2( |
18 |
, |
14, 58 |
) |
); |
15 |
list.add( |
new |
Time2( |
6 |
, |
05, 34 |
) |
); |
16 |
list.add( |
new |
Time2( |
12 |
, |
14, 58 |
) |
); |
17 |
list.add( |
new |
Time2( |
6 |
, |
24, 22 |
) |
); |
18 |
|
|
|
|
|
|
|
|
19// output List elements
20System.out.printf( "Unsorted array elements:\n%s\n", list );
22// sort in order using a comparator
23Collections.sort( list, new TimeComparator() );
25// output List elements
26System.out.printf( "Sorted list elements:\n%s\n", list );
27} // end method printElements
29public static void main( String args[] )
30{
31Sort3 sort3 = new Sort3();
32sort3.printElements();
33} // end main
34} // end class Sort3
Unsorted array elements:
[6:24:34 AM, 6:14:58 PM, 6:05:34 AM, 12:14:58 PM, 6:24:22 AM] Sorted list elements:
[6:05:34 AM, 6:24:22 AM, 6:24:34 AM, 12:14:58 PM, 6:14:58 PM]
[Page 927]
19.6.2. Algorithm shuffle
Algorithm shuffle randomly orders a List's elements. In Chapter 7, we presented a card shuffling and dealing simulation that used a loop to shuffle a deck of cards. In Fig. 19.12, we use algorithm shuffle to shuffle a deck of Card objects that might be used in a card game simulator.
Figure 19.12. Card shuffling and dealing with Collections method
shuffle.
(This item is displayed on pages 927 - 929 in the print version)
1// Fig. 19.12: DeckOfCards.java
2// Using algorithm shuffle.
3import java.util.List;
4import java.util.Arrays;
5import java.util.Collections;
6
7 // class to represent a Card in a deck of cards
8class Card
9{
10
11
12
13
14private final Face face; // face of card
15private final Suit suit; // suit of card
17// two-argument constructor
18public Card( Face cardFace, Suit cardSuit )
19{
20face = cardFace; // initialize face of card
21suit = cardSuit; // initialize suit of card
22} // end two-argument Card constructor
23
24// return face of the card
25public Face getFace()
26{
27return face;
28} // end method getFace
29
30// return suit of Card
31public Suit getSuit()
32{
33return suit;
34} // end method getSuit
36// return String representation of Card
37public String toString()
38{
39return String.format( "%s of %s", face, suit );
40} // end method toString
41} // end class Card
42
43// class DeckOfCards declaration
44public class DeckOfCards
45{
46 |
private List< Card > list; // declare List that will store Cards |
47 |
|
48// set up deck of Cards and shuffle
49public DeckOfCards()
50{
51Card[] deck = new Card[ 52 ];
52int count = 0; // number of cards
54// populate deck with Card objects
55for ( Card.Suit suit : Card.Suit.values() )
56{
57for ( Card.Face face : Card.Face.values() )
58{
59 |
deck[ count ] = new Card( face, suit ); |
60 |
count++; |
61} // end for
62} // end for
63
64list = Arrays.asList( deck ); // get List
65Collections.shuffle( list ); // shuffle deck
66} // end DeckOfCards constructor
67
68// output deck
69public void printCards()
70{
71// display 52 cards in two columns
72 |
for ( |
int |
i |
= |
0; i < |
list.size(); i++ |
) |
|
73 |
System.out |
.printf( |
"%-20s%s", list.get( |
i ), |
||||
74 |
|
( ( |
i |
+ |
1 ) % 2 |
== 0 ) ? "\n" : "\t" |
); |
|
75 |
} // end |
method |
|
printCards |
|
|
||
76 |
|
|
|
|
|
|
|
|
77public static void main( String args[] )
78{
79DeckOfCards cards = new DeckOfCards();
80cards.printCards();
81} // end main
82} // end class DeckOfCards
King |
|
of |
|
Diamonds |
Jack |
|
of |
Spades |
|
Four |
|
of |
|
Diamonds |
Six |
of |
Clubs |
||
King |
|
of |
|
Hearts |
Nine |
|
of |
Diamonds |
|
Three |
of |
Spades |
Four |
|
of |
Spades |
|||
Four |
|
of |
|
Hearts |
Seven |
|
of |
Spades |
|
Five |
|
of |
|
Diamonds |
Eight |
|
of |
Hearts |
|
Queen |
of |
Diamonds |
Five |
|
of |
Hearts |
|||
Seven |
of |
Diamonds |
Seven |
|
of |
Hearts |
|||
Nine |
|
of |
|
Hearts |
Three |
|
of |
Clubs |
|
Ten |
of |
Spades |
Deuce |
|
of |
Hearts |
|||
Three |
of |
Hearts |
Ace |
of |
Spades |
||||
Six |
of |
Hearts |
Eight |
|
of |
Diamonds |
|||
Six |
of |
Diamonds |
Deuce |
|
of |
Clubs |
|||
Ace |
of |
Clubs |
Ten |
of |
Diamonds |
||||
Eight |
of |
Clubs |
Queen |
|
of |
Hearts |
|||
Jack |
|
of |
|
Clubs |
Ten |
of |
Clubs |
||
Seven |
of |
Clubs |
Queen |
|
of |
Spades |
|||
Five |
|
of |
|
Clubs |
Six |
of |
Spades |
||
Nine |
|
of |
|
Spades |
Nine |
|
of |
Clubs |
|
King |
|
of |
|
Spades |
Ace |
of |
Diamonds |
||
Ten |
of |
Hearts |
Ace |
of |
Hearts |
||||
Queen |
of |
Clubs |
Deuce |
|
of |
Spades |
|||
Three |
of |
Diamonds |
King |
|
of |
Clubs |
|||
Four |
|
of |
|
Clubs |
Jack |
|
of |
Diamonds |
|
Eight |
of |
Spades |
Five |
|
of |
Spades |
|||
Jack of Hearts |
Deuce of Diamonds |
|
|
Class Card (lines 841) represents a card in a deck of cards. Each Card has a face and a suit. Lines 1012 declare two enum typesFace and Suitwhich represent the face and the suit of the card, respectively. Method toString (lines 3740) returns a String containing the face and suit of the Card separated by the string " of ". When an enum constant is converted to a string, the constant's identifier is used as the string representation. Normally we would use all uppercase letters for enum constants. In this example, we chose to use capital letters for only the first letter of each enum constant because we want the card to be displayed with initial capital letters for the face and the suit (e.g., "Ace of Spades").
[Page 929]
Lines 5562 populate the deck array with cards that have unique face and suit combinations. Both Face and Suit are public static enum types of class Card. To use these enum types outside of class Card, you must qualify each enum's type name with the name of the class in which it resides (i.e., Card) and a dot (.) separator. Hence, lines 55 and 57 use Card.Suit and Card.Face to declare the control variables of the for statements. Recall that method values of an enum type returns an array that contains all the constants of the enum type. Lines 5562 use enhanced for statements to construct 52 new Cards.
[Page 930]
The shuffling occurs in line 65, which calls static method shuffle of class Collections to shuffle the elements of the array. Method shuffle requires a List argument, so we must obtain a List view of the array before we can shuffle it. Line 64 invokes static method asList of class Arrays to get a List view of the deck array.
Method printCards (lines 6975) displays the deck of cards in two columns. In each iteration of the loop, lines 7374 output a card left justified in a 20-character field followed by either a newline or an empty string based on the number of cards output so far. If the number of cards is even, a newline is output; otherwise, a tab is output.
19.6.3. Algorithms reverse, fill, copy, max and min
Class Collections provides algorithms for reversing, filling and copying Lists. Algorithm reverse reverses the order of the elements in a List, and algorithm fill overwrites elements in a List with a specified value. The fill operation is useful for reinitializing a List. Algorithm copy takes two argumentsa destination List and a source List. Each source List element is copied to the destination List. The destination List must be at least as long as the source List; otherwise, an IndexOutOfBoundsException occurs. If the destination List is longer, the elements not overwritten are unchanged.
Each of the algorithms we have seen so far operates on Lists. Algorithms min and max each operate on any Collection. Algorithm min returns the smallest element in a Collection, and algorithm max returns the largest element in a Collection. Both of these algorithms can be called with a Comparator object as a second argument to perform custom comparisons of objects, such as the TimeComparator in Fig. 19.11. Figure 19.13 demonstrates the use of algorithms reverse, fill, copy, min and max. Note that the generic type List is declared to store Characters.
Figure 19.13. Collections methods reverse, fill, copy, max and min.
(This item is displayed on pages 930 - 931 in the print version)
1 // Fig. 19.13: Algorithms1.java
2 // Using algorithms reverse, fill, copy, min and max.
3import java.util.List;
4import java.util.Arrays;
5import java.util.Collections;
7public class Algorithms1
8{
