In this chapter you learn about the java.util package. This package provides some of the most useful Java classes that you will come to rely on. It introduces the following nonabstract classes:
BitSet
Date
Hashtable
Properties
Observable
Random
Vector
Stack
StringTokenizer
The BitSet class is useful for storing and manipulating arbitrarily long sets of bits. The Date class can be used to represent dates and times, and provides methods for converting dates to and from strings. The Hashtable class can be used for creating an array of keys and values and allowing elements to be looked up by either key or value. The Properties class extends Hashtable by allowing elements to be streamed into or out of the class. The Observable class can be extended, and enables you to create new classes that will notify other classes when they change. It works in conjunction with the Observer interface, which is also part of the java.util package.
The Random class is a pseudo-random number generator that can return integer, floating-point, or Gaussian-distributed values. The Stack class is an extension of Vectorand supplies a last-in-first-out (LIFO) data structure. The Vector class can be used for storing any objects and can store objects of more than one type in the same vector. The StringTokenizer class provides a flexible mechanism for parsing strings.
The BitSet class represents a dynamically sized set of bits. Two constructors are provided, one that creates an empty set of unspecified size and one that creates a set of a specified size. The set method can be used to set an individual bit or clear can be used to clear an individual bit. The first bit in a BitSet is the zero bit so thatmyBitset.set(0) is a valid statement.
The logical functions and, or, and xor are all supported and will combine the BitSet with another set. BitSets can be compared for equality using equals and can be converted to strings using toString. For the purpose of converting a BitSet to a string, a set bit is represented by the value 1 and a clear bit is represented by 0.
The available constructor and nonprivate methods for BitSet are shown in Table 11.1.
Table 11.1. Public constructors and methods of BitSet.
Member | Purpose |
BitSet() | Constructs an empty bit set. |
BitSet(int) | Constructs an empty bit set with the specified number of bits. |
And(BitSet) | Logically ANDs two bit sets. |
Clear(int) | Clears the specified bit. |
Clone() | Creates a duplicate copy of the BitSet. |
Equals(Object) | Returns true if two BitSets are equal. |
Get(int) | Returns the value of the specified bit. |
HashCode() | Returns a hash code for the bit set. |
Or(BitSet) | Logically ORs two bit sets. |
Set(int) | Sets the specified bit. |
Size() | Returns the size of the bit set in bits. |
ToString() | Formats the BitSet as a string. |
Xor(BitSet) | Logically XORs two bit sets. |
As an example of how to use BitSet consider class EX11A, shown in Listing 11.1. In this example, the method BitSetTest is invoked as the result of the user pressing a button. As various operations on BitSets are performed, a TextArea is updated to display the results of the operations.
import java.applet.*;
import java.awt.*;
import java.util.*;
public class EX11A extends Applet
{
TextArea results = new TextArea(10, 20);
public void init()
{
add(new Button("Start"));
add(results);
resize(320, 240);
}
public boolean action(Event evt, Object obj)
{
boolean result=false;
if("Start".equals(obj)) {
BitSetTest();
result = true;
}
return result;
}
void BitSetTest()
{
// create a BitSet and set items 1 and 4
BitSet bits1 = new BitSet(10);
bits1.set(1);
bits1.set(4);
// create a BitSet and set items 4 and 5
BitSet bits2 = new BitSet(10);
bits2.set(4);
bits2.set(5);
// display the contents of these two BitSets
results.appendText("Bits 1=" + bits1.toString() + "\r\n");
results.appendText("Bits 2=" + bits2.toString() + "\r\n");
// test for equality of the two BitSets
if(bits1.equals(bits2))
results.appendText("bits1 == bits2\r\n");
else
results.appendText("bits1 != bits2\r\n");
// create a clone and then test for equality
BitSet clonedBits = (BitSet)bits1.clone();
if(bits1.equals(clonedBits))
results.appendText("bits1 == clonedBits\r\n");
else
results.appendText("bits1 != clonedBits\r\n");
// logically AND the first two BitSets
bits1.and(bits2);
results.appendText("ANDing bits1 and bits2\r\n");
// and display the resulting BitSet
results.appendText("bits1=" + bits1.toString() + "\r\n");
}
}
In the BitSetTest method, two BitSets are constructed. The first, bits1, has bits 1 and 4 set. The second, bits2, has bits 4 and 5 set. The toString method is used to display the contents of the BitSets. The BitSets are then compared using equals. Next, a clone of bits1 is created. To show that the clone method was successful, theBitSets are compared and a message is displayed. Finally, the and method is used to logically AND two BitSets and the result is displayed using toString.
NOTE |
Because the BitSet class is contained in the package java.util, be sure to import java.util, as done on the third line of Listing 11.1 |
The Date class stores a representation of a date and time, and provides methods for manipulating the date and time components. As summarized in Table 11.2, constructors are provided that will create a new Date instance based on the current date and time, the number of milliseconds since midnight on January 1, 1970, a string, or from integers representing the year, month, day, hours, minutes, and seconds.
Table 11.2. Constructors for the Date class.
Constructor | Purpose |
Date() | Creates a Date using today's date. |
Date(long) | Creates a Date using the specified number of milliseconds since January 1, 1970. |
Date(int,int,int) | Creates a Date using the specified year, month, and day. |
Date(int,int,int,int,
int) | Creates a Date using the specified year, month, day, hours, and minutes. |
Date(int,int,int,int,
int,int) | Creates a Date using the specified year, month, day, hours, minutes, and seconds. |
Date(String) | Creates a Date using the specified string. |
As examples of how these constructors can be used to create new Date objects, consider the following:
Date date1 = new Date();
Date date2 = new Date(95, 10, 14);
Date date3 = new Date(95, 10, 14, 13, 16, 45);
Date date4 = new Date("14 November 1995 13:16:45");
In this case, date1 will be set to the current date and time. The date2 variable will be set to November 14, 1995. Months are zero-based in the Date class, so 10 is passed as a parameter to indicate the eleventh month. The third example adds more exactness to the second example. While date2 will represent the stroke of midnight on November 14, 1995, date3 is explicitly set to 13:16: 45 (45 seconds after 1:16 p.m.). Finally, date4 creates the same time as date3, but does so from a string.
Many methods are also provided for manipulating Date instances. For example, dates can be compared with the before, after, and equals methods. Methods are also provided for converting a Date into various formatted strings. The nonprivate instance methods of the Date class are shown in Table 11.3.
Table 11.3. Nonprivate instance methods of the Date class.
Method | Purpose |
after(Date) | Returns true if the Date occurs after the specified Date. |
Before(Date) | Returns true if the Date occurs before the specified Date. |
Equals(Object) | Returns true if two Dates are equal. |
GetDate() | Returns the day (1-31) portion of the Date. |
GetDay() | Returns the day of the week (Sunday is 0)indicated by the Date. |
GetHours() | Returns the hours (0-23) portion of the Date. |
GetMinutes() | Returns the minutes (0-59) portion of the Date. |
GetMonth() | Returns the month (0-11) portion of the Date. |
GetSeconds() | Returns the seconds (0-59) portion of the Date. |
GetTime() | Returns the number of milliseconds since midnight on January 1, 1970. |
GetTimezoneOffset() | Returns the offset in minutes for the current timezone from UTC (Coordinated Universal Time, similar to GMT, Greenwich Mean Time). |
GetYear() | Returns the year after 1900. |
HashCode() | Returns a hash code for the Date. |
SetDate(int) | Sets the day of the month. |
SetHours(int) | Sets the hours. |
SetMinutes(int) | Sets the minutes. |
SetMonth(int) | Sets the month. |
SetSeconds(int) | Sets the seconds. |
SetTime(long) | Sets the time to the specified number of milliseconds since midnight January 1, 1970. |
SetYear(int) | Sets the year after 1900. |
ToGMTString() | Returns a formatted string of the Date in the GMT time zone. |
ToLocaleString() | Returns a formatted string of the Date in the current time zone. |
ToString() | Returns a formatted string of the Date including the day of the week. |
In addition to the instance methods shown in Table 11.3, the Date class includes two static methods. Static methods can be invoked without an instance of the class. The static methods of the Date class can be used to determine the number of seconds since midnight on January 1, 1970 based on a string or integer values representing the date and time. These are summarized in Table 11.4; examples of their use are as follows:
long temp = Date.parse("14 November 1996");
Date date1 = new Date(temp);
temp = Date.UTC(96, 10, 14, 13, 16, 45);
Date date2 = new Date(temp);
Table 11.4. Static methods of the Date class.
Method | Purpose |
UTC(int,int,int,int,
int,int) | Returns the milliseconds since midnight January 1, 1970 based on the year, month, day, hours, minutes, and seconds parameters. |
Parse(String) | Returns the milliseconds since midnight January 1, 1970 based on parsing the supplied string. |
As an example of the use of the Date class, consider example EX11B, as shown in Listing 11.2. The init method of this class displays a TextArea and then creates a Date object based on the current date. The toString, toLocaleString, and toGMTString methods are used to display the current date in various formats. An instance named BastilleDay is then constructed using the date of that holiday. Next, the year value for BastilleDay is set to the current year using the setYear and getYear methods. Finally, after is used to determine whether Bastille Day has already occurred this year, or if there is still time to shop for presents for your French friends. The results of executing this class are shown in Figure 11.1.
import java.applet.*;
import java.awt.*;
import java.util.*;
public class EX11B extends Applet
{
TextArea results = new TextArea(10, 50);
public void init()
{
add(results);
Date today = new Date(); // today
// display the current date in a couple of different formats
results.appendText("Today is:" + today.toString() + "\r\n");
results.appendText("Locale Time:" + today.toLocaleString() + "\r\n");
results.appendText("GMT:" + today.toGMTString() + "\r\n");
// store Bastille Day (July 14th) in an instance
Date BastilleDay = new Date(96, 6, 14); // 7-14-96
// set Bastille Day to be in the current year
BastilleDay.setYear(today.getYear());
// see if we've already missed Bastille Day
if (today.after(BastilleDay))
results.appendText("You missed Bastille Day!\r\n");
else
results.appendText("Bastille Day is coming!\r\n");
resize(320, 240);
}
}
The Hashtable class extends the abstract Dictionary class that is also defined in the java.util package. A Hashtable is used for mapping keys to values. For example, it could be used to map names to ages, programmers to projects, job titles to salaries, and so on.
A Hashtable will expand in size as elements are added to it. When creating a new Hashtable you can specify an initial capacity and a load factor. The Hashtable will increase in size whenever adding a new element would move the Hashtable past its threshold. A Hashtable's threshold is its capacity multiplied by its load factor. For example, a Hashtable with a capacity of 100 and a load factor of 0.75 would have a threshold of 75 items. The constructors for Hashtable are shown in Table 11.5.
Table 11.5. Constructors for the Hashtable class.
Constructor | Purpose |
Hashtable(int) | Constructs a new Hashtable with the specified initial capacity. |
Hashtable(int, float) | Constructs a new Hashtable with the specified initial capacity and load factor. |
Hashtable() | Constructs a new Hashtable using default values for initial capacity and load factor. |
As an example of how to construct a new Hashtable, consider the following:
Hashtable hash1 = new Hashtable(500, .80);
In this case a Hashtable is constructed that will hold 500 elements. When the Hashtable becomes 80 percent full (a load factor of .80), its maximum size will be increased.
Each element in a Hashtable consists of a key and value. Elements are added to a Hashtable using the put method and are retrieved using get. Elements may be deleted from a Hashtable with remove. The contains and containsKey methods can be used to look up a value or key in the Hashtable. These and other Hashtablemethods are summarized in Table 11.6.
Table 11.6. Nonprivate methods of the Hashtable class.
Method | Purpose |
clear() | Removes all elements from the Hashtable. |
clone() | Creates a clone of the Hashtable. |
contains(Object) | Returns true if the Hashtable contains the specified object. |
containsKey(Object) | Returns true if the Hashtable contains the specified key. |
elements() | Returns an enumeration of the elements in the Hashtable. |
get(Object) | Retrieves the object associated with the specified key. |
isEmpty() | Returns true if the Hashtable is empty. |
keys() | Returns an enumeration of the keys in the Hashtable. |
put(Object, Object) | Adds a new element to the Hashtable using the specified key and value. |
rehash() | Rehashes the Hashtable into a larger Hashtable. |
remove(Object) | Removes the object given by the specified key. |
size() | Returns the number of elements in the Hashtable. |
toString() | Returns a formatted string representing the Hashtable. |
Class EX11C, shown in Listing 11.3, demonstrates how to use the Hashtable class. In this example a new Hashtable, ht, is constructed and is used to store the five best albums released by Pink Floyd. The Hashtable is displayed to a TextArea using toString.
import java.applet.*;
import java.awt.*;
import java.util.*;
public class EX11C extends Applet
{
TextArea results = new TextArea(10, 75);
public void init()
{
add(results);
// create a new Hashtable
Hashtable ht = new Hashtable();
// add Pink Floyd's best albums
ht.put("Pulse", new Integer(1995));
ht.put("Dark Side of the Moon", new Integer(1973));
ht.put("Wish You Were Here", new Integer(1975));
ht.put("Animals", new Integer(1977));
ht.put("Ummagumma", new Integer(1969));
// display the Hashtable
results.appendText("Initailly: "+ht.toString() + "\r\n");
// test for any album from 1969
if (ht.contains(new Integer(1969)))
results.appendText("An album from 1969 exists\r\n");
// test for the Animals album
if (ht.containsKey("Animals"))
results.appendText("Animals was found\r\n");
// find out what year Wish You Were Here was released
Integer year = (Integer)ht.get("Wish You Were Here");
results.appendText("Wish You Were Here was released in " +
year.toString() + "\r\n");
// remove an album
results.appendText("Removing Ummagumma\r\n");
ht.remove("Ummagumma");
// move through an enumeration of all keys in the table
results.appendText("Remaining:\r\n");
for (Enumeration enum=ht.keys(); enum.hasMoreElements() ;)
results.appendText((String)enum.nextElement()+"\r\n");
// and resize the applet window
resize(500, 240);
}
}
In this Hashtable, the names of the albums are the keys and the years are the elements. Therefore, contains is used to look up the integer element 1969 to see whether the list contains any albums from 1969. Similarly, containsKey is used to search for the key "Animals" to see if that album made the list. Next, the get method is used to see whether "Wish You Were Here" is in the Hashtable. Because get returns the element associated with the key, both the name and year are displayed at this point. This can be seen in Figure 11.2.
Next, I had some second thoughts about including "Ummagumma" in a list of best albums and used remove to delete it from the Hashtable. Finally, the keys method is used to create an Enumeration of the keys stored in the Hashtable. The applet then iterates through the enumeration using enum.hasMoreElements andenum.nextElement.
The Properties class extends Hashtable and adds the capability to read and write a Hashtable to a stream. Because an applet cannot access files, the Propertiesclass is useful only for applications.
Like Hashtable, this class can be used to store keys and associated values. Through its save and load methods, Properties can be written to disk. This makes this class an excellent mechanism for storing configuration information between runs of a program. An example of a Properties file written by the save method is as follows:
#This is a header comment
#Sat Sep 14 15:55:15 Pacific Daylight Time 1996
prop3=put three
prop2=put two
prop1=put one
Because Properties is a subclass of Hashtable, new key/value pairs are added using the put method of Hashtable. The constructors and nonprivate methods ofProperties are shown in Table 11.7.
Table 11.7. Nonprivate constructors and methods of Properties class.
Member | Purpose |
Properties() | Creates a new Properties object. |
Properties(Properties) | Creates a new Properties object based on the specified default values. |
GetProperty(String) | Returns the property value associated with the specified key. |
GetProperty(String,String) | Returns the property value associated with the specified key. If the key is not found, the specified default is returned. |
List(PrintStream) | Lists all of the properties to the specified PrintStream. |
Load(InputStream) | Reads a set of properties from the specified InputStream. |
PropertyNames() | Returns an Enumeration of all property names. |
Save(OutputStream, String) | Saves the Properties and a header string to the specified OutputStream. |
Example EX11D, shown in Listing 11.4, shows how to create an instance, put three properties into it, save it, and then reload the keys and values into a different instance.
import java.awt.*;
import java.io.*;
import java.util.*;
public class EX11D
{
public static void main(String[] args)
{
// create a new instance
Properties props1 = new Properties();
// put three properties into it
props1.put("prop1", "put one");
props1.put("prop2", "put two");
props1.put("prop3", "put three");
// retrieve each of the three properties
String prop1 = props1.getProperty("prop1", "one");
String prop2 = props1.getProperty("prop2", "two");
String prop3 = props1.getProperty("prop3");
// save the properties to a file
try
{
props1.save(new FileOutputStream("test.ini"), "My header");
}
catch (IOException e) {
return;
}
// create a new instance and read the file in from the file
Properties props2 = new Properties();
try
{
FileInputStream inStr = new FileInputStream("test.ini");
props2.load(inStr);
}
catch (IOException e) {
return;
}
// retrieve a property from the second instance
String prop = props2.getProperty("prop2", "two");
}
}
This class represents a pseudo-random number generator. Two constructors are provided, one taking a seed value as a parameter and the other taking no parameters and using the current time as a seed. Constructing a random number generator with a seed value is a good idea unless you want the random number generator to always generate the same set of values. On the other hand, sometimes it is useful to generate the same sequence of "random" numbers. This is frequently useful while debugging a program.
Once the random number generator is created, a value can be retrieved from it using any of the following methods:
nextDouble
nextFloat
nextGaussian
nextInt
nextLong
The constructors and methods of Random are summarized in Table 11.8. Use of the Random class is very simple, so no example is presented here. However, exampleEX11E, shown in the following discussion of the Observer class, also uses Random.
Table 11.8. Nonprivate constructors and methods of Random class.
Method | Purpose |
Random() | Creates a new random number generator. |
Random(long) | Creates a new random number generator based on the specified seed value. |
nextDouble() | Returns the next double value between 0.0D and 1.0D from the random number generator. |
nextFloat() | Returns the next float value between 0.0F and 1.0F from the random number generator. |
NextGaussian() | Returns the next Gaussian-distributed double from the random number generator. Generated Gaussian values will have a mean of 0 and a standard deviation of 1.0. |
nextInt() | Returns the next integer value from the random number generator. |
nextLong() | Returns the next long value from the random number generator. |
setSeed(long) | Sets the seed value for the random number generator. |
An Observable class is a class that may be watched or monitored by another class that implements the Observer interface. Associated with each Observable instance is a list of Observers. Whenever the Observable instance changes it can notify each of its Observers. By using Observable and Observer classes you can achieve a better partitioning of your code by decreasing the reliance of one class or another.
The Observable class includes a single constructor that takes no parameters. It also includes a number of methods for managing its list of Observers. These are summarized in Table 11.9.
Table 11.9. Nonprivate constructors and methods of Observer class.
Member | Purpose |
Observable() | Creates a new Observable instance. |
addObserver(Observer) | Adds an Observer to the list of objects observing this instance. |
clearChanged() | Clears the internal flag used to indicate that an Observable object has changed. |
countObservers() | Returns the number of Observers of this object. |
deleteObserver(Observer) | Deletes an Observer from the list of Observers of this object. |
deleteObservers() | Deletes all Observers of this object. |
hasChanged() | Returns true if the object has changed. |
notifyObservers() | Notifies all Observers that a change has occurred in the Observable object. |
notifyObservers(Object) | Notifies all Observers that a change has occurred and passes them the specified argument. |
setChanged() | Sets the internal flag to indicate that a change has occurred. |
The Observer interface defines an update method that is invoked by an Observable object whenever the Observable object has changed and wants to notify itsObservers. The signature of update is as follows:
public abstract void update(Observable o, Object arg);
This method is called whenever an Observable instance that is being observed invokes either of its notifyObservers methods. It is passed the Observable object that changed and an optional additional parameter.
As an example of how Observable can be used, consider the declaration of the Obsable class in Listing 11.5. The Obsable class stores a secret number that is generated by a random number generator. Whenever the secret number changes, all Observers are notified.
import java.applet.*;
import java.awt.*;
import java.util.*;
// define a class that stores a secret number
class Obsable extends Observable {
private int secretNumber;
private Random generator;
public Obsable(int seed) {
// create a random number generator that will
// make the "secret numbers"
generator = new Random(seed);
}
public void GenerateNumber() {
// generate a new secret number
secretNumber = generator.nextInt();
// indicate to Observable that the instance has changed
setChanged();
// notify all of the observers and pass the new number
notifyObservers(new Integer(secretNumber));
}
}
public class EX11E extends Applet implements Observer
{
Integer secretNumber;
Obsable obs;
TextField tf;
public EX11E()
{
// create a new instance of the observable class
obs = new Obsable(12);
// indicate that "this" is an observer
obs.addObserver(this);
// create a read-only TextField
tf = new TextField(10);
tf.setEditable(false);
}
public void init() {
add(new Label("Secret Number:"));
add(tf);
add(new Button("Change"));
resize(320, 240);
}
// this method is invoked when the observable object
// notifies its observers
public void update(Observable o, Object arg) {
// store the secret number and display it
secretNumber = (Integer)arg;
tf.setText(String.valueOf(secretNumber));
}
public boolean action(Event evt, Object obj)
{
boolean result=false;
if("Change".equals(obj)) {
obs.GenerateNumber();
result = true;
}
return result;
}
}
No Observable class is complete without an Observer, so Listing 11.5 also includes class EX11E, which extends Applet and implements the Observer interface. The results of executing this applet are shown in Figure 11.3. The constructor for EX11E creates an instance of Obsable, the Observable class defined previously and adds the applet as an observer of the Observable object. The init method places a label, TextField, and button on the screen. The TextField will be used to display the current value of the secret number.
The EX11E class contains an update method that is part of the Observer interface. This method is passed an Observable item and an Object as parameters. As shown in the declaration of Obsable, the Object is an integer. Therefore, update casts the Object into an Integer, stores it in the instance variable secretNumber, and then updates the TextField.
The action method traps pushes of the Change button and then calls obs.GenerateNumber to generate a new random number. Each time GenerateNumber changes the secret number, the update method in the observer will be called. In this case, this will update the display with each newly generated random number.
One of the problems with an array is that you must know how big it must be when you create it. This is not always practical and is rarely easy. Imagine what would have happened if the founding fathers of the United States were programmers and they used a 13-element array to hold the names of all the states. Even if the lead programmer on this project (Thomas Jefferson, if I remember my eighth grade history correctly) had the foresight to double or triple the array size to allow for future growth, it still would not have been enough.
The Java Vector class solves this problem by providing a form of resizable array that can grow as more elements are added to it. A Vector stores items of type Object so that it can be used to store instances of any Java class. A single Vector may store different elements that are instances of different classes.
At any point in time a Vector has the capacity to hold a certain number of elements. When a Vector reaches its capacity, its capacity is incremented by an amount specific to that Vector. The Vector class provides three different constructors that enable you to specify the initial capacity and increment quantity of a Vector when it is created. These constructors are summarized in Table 11.10.
Table 11.10. Constructors for the Vector class.
Constructor | Purpose |
Vector(int) | Creates a new Vector with the specified initial capacity. |
Vector(int, int) | Creates a new Vector with the specified initial capacity and increment quantity. |
Vector() | Creates a new Vector with defaults for the initial capacity and increment quantity. |
An item is added to a Vector using addElement. Similarly, an element can be replaced using setElementAt. A Vector can be searched using the contains method, which simply looks for an occurrence of an Object. The elements method is useful because it returns an enumeration of the Objects stored in the Vector. These and other member methods of Vector are summarized in Table 11.11.
Table 11.11. Nonprivate methods of the Vector class.
Method | Purpose |
addElement(Object) | Inserts the specified element into the Vector. |
capacity() | Returns the number of elements that will fit into the currently allocated portion of the Vector. |
clone() | Clones the vector, but not its elements. |
contains(Object) | Returns true if the Vector contains the specified Object. |
copyInto(Object []) | Copies the elements of the Vector into the specified array. |
elementAt(int) | Retrieves the element located at the specified index. |
elements() | Returns an enumeration of the elements in the Vector. |
ensureCapacity(int) | Ensures that the Vector can hold at least the specified minimum capacity. |
firstElement() | Returns the first element in the Vector. |
indexOf(Object) | Searches the Vector and returns the zero-based index of the first matchingObject. |
indexOf(Object, int) | Searches the Vector beginning at the specified index number and returns the zero-based index of the next matching Object. |
insertElementAt(Object, int) | Adds the specified Object at the specified index. |
isEmpty() | Returns true if the Vector has no elements. |
LastElement() | Returns the last element in the Vector. |
lastIndexOf(Object) | Searches the Vector and returns the zero-based index of the last matchingObject. |
lastIndexOf(Object, int) | Searches the Vector beginning at the specified index number and returns the zero-based index of the prior matching Object. |
removeAllElements() | Removes all elements from the Vector. |
removeElement(Object) | Removes the specified Object from the Vector. |
removeElementAt(int) | Removes the Object at the specified index. |
setElementAt(Object, int) | Replaces the Object at the specified index with the specified Object. |
setSize(int) | Sets the size of the Vector to the specified new size. |
size() | Returns the number of elements currently in the Vector. |
toString() | Returns a formatted string representing the contents of the Vector. |
trimToSize() | Removes any excess capacity in the Vector by resizing it. |
As an example of using Vector consider example class EX11F, shown in Listing 11.6. This example again uses a TextArea to display the results of various operations. In this example, a Vector, v1, is constructed. Initially, enough space is reserved for 10 elements and the Vector will increase its capacity by four whenever there is no room for a new element.
import java.applet.*;
import java.awt.*;
import java.util.*;
public class EX11F extends Applet
{
TextArea results = new TextArea(10, 75);
public void init()
{
resize(500, 240);
add(results);
// create a new Vector to hold 10 elements
// and to increase by 4 each time it's necessary
Vector v1 = new Vector(10, 4);
// add elements, both Integer and String, to the Vector
v1.addElement(new Integer(1));
v1.addElement(new Integer(2));
v1.addElement(new Integer(3));
v1.addElement("Four");
v1.addElement(new Integer(5));
// display the entire Vector
results.appendText(v1.toString() + "\r\n");
// see if the Vector contains this Integer
if (v1.contains(new Integer(2)))
results.appendText("It contains 2\r\n");
// see if the Vector contains this String
if (v1.contains("Four"))
results.appendText("It contains Four\r\n");
// Display the capacity of the Vector
int capacity = v1.capacity();
results.appendText("Can hold " +
String.valueOf(capacity) + "\r\n");
// Display the element at index number 3
results.appendText("ElementAt 3 = " +
(String)v1.elementAt(3) + "\r\n");
// clear out the Vector
v1.removeAllElements();
// add the names of Pink Floyd's first five albums
v1.addElement("Piper At The Gates of Dawn");
v1.addElement("Saucerful of Secrets");
v1.addElement("Ummagumma");
v1.addElement("Meddle");
v1.addElement("The Dark Side of the Moon");
// use an enumeration to display each of the album titles
for (Enumeration enum = v1.elements();
enum.hasMoreElements(); )
results.appendText((String)enum.nextElement()+"\r\n");
}
}
Initially, five elements-four integers and one string-are added to the Vector. This illustrates the capability to store objects of different types in the same Vector. Next, thetoString method is used to display the entire Vector. This, along with the other messages displayed by EX11F, can be seen in Figure 11.4.
Next, the contains method is used to determine if the Vector contains the Integer 2 and the string "Four". The capacity of the Vector is then displayed and the item at index number three is retrieved and displayed. Because Vector is zero-based this will retrieve the fourth element in the Vector.
The method removeAllElements is then used to remove the current elements. The names of Pink Floyd's first five albums are then added to the Vector. Finally, theelements method is used to return an Enumeration of the elements. The hasMoreElements and nextElement method are used in a loop that displays each of the album titles.
The Stack class extends Vector and implements a simple last-in-first-out stack. An item is stored on a stack by "pushing" it onto the stack. An item may subsequently be "popped" off the stack and used. The item popped off a stack will always be the most recently pushed item.
Because Stack extends the Vector class, no size is associated with a Stack instance. The Stack will continue to grow in size as new items are pushed onto it. In addition to methods to push and pop items, a peek method is provided for looking at the next item, a search method is provided for scanning the Stack for a specific item, and anempty method is provided determining whether more items are stored in the Stack.
The single constructor as well as the nonprivate methods of Stack are summarized in Table 11.12.
Table 11.12. Constructors and nonprivate methods of the Stack class.
Member | Purpose |
Stack() | Creates a new Stack. |
empty() | Returns true if the Stack is empty. |
peek() | Returns the last Object added to the Stack but does not remove it from the Stack. |
pop() | Returns the last Object added to the Stack and removes it. |
push(Object) | Adds the specified Object to the Stack. |
search(Object) | Searches for the specified Object in the Stack. |
An example of using Stack is provided in example EX11G, shown in Listing 11.7. In this example a Stack is created and three items are added to it. The toString method is used to display the Stack's initial contents. The peek method is used to look at the last object added to the Stack but does not actually remove the object. Next, searchis used to look for an occurrence of "2" within the Stack. Finally, pop is used to remove an object from the Stack and toString is used to redisplay its contents. The results of executing this applet are shown in Figure 11.5.
import java.applet.*;
import java.awt.*;
import java.util.*;
public class EX11G extends Applet
{
TextArea results = new TextArea(10, 30);
public void init()
{
resize(320, 240);
add(results);
// create a new Stack
Stack stk = new Stack();
// add three items to the Stack
stk.push("1");
stk.push("2");
stk.push("3");
// display the entire Stack
results.appendText("Stack=" + stk.toString() + "\r\n");
// peek at what's next off the stack
String str = (String)stk.peek();
results.appendText("Peeked at: " + str + "\r\n");
// see if there's a "2" anywhere in the Stack
if (stk.search("2") != -1)
results.appendText("Found 2\r\n");
// pop an item off the Stack
str = (String)stk.pop();
results.appendText("Popped: " + str + "\r\n");
// display the entire Stack
results.appendText("Stack=" + stk.toString() + "\r\n");
}
}
A StringTokenizer can be used to parse a string into its constituent tokens. For example, each word in a sentence could be considered a token. However, theStringTokenizer class goes beyond the parsing of sentences. You can create a fully customized tokenizer by specifying the set of token delimiters when theStringTokenizer is created. For parsing text, the default whitespace delimiters are usually sufficient. However, you could use the set of arithmetic operators (+, *, /, and-) if parsing an expression.
The delimiter characters can be specified when a new StringTokenizer object is constructed. Table 11.13 summarizes the three available constructors. Examples of using these constructors are the following:
StringTokenizer st1 = new StringTokenizer("A stream of words");
StringTokenizer st2 = new StringTokenizer("4*3/2-1+4", "*+/-", true);
StringTokenizer st3 = new StringTokenizer("aaa,bbbb,ccc", ",");
In the first example, the st1 StringTokenizer will be constructed using the supplied string and the default delimiters. The default delimiters are the space, tab, newline, and carriage return characters. These delimiters are useful when parsing text, as with st1. The second example constructs a StringTokenizer for tokenizing arithmetic expressions using the *, +, /, and - symbols as supplied. Finally, the third StringTokenizer, st3, will tokenize the supplied string using only the comma character as a delimiter.
Table 11.13. Constructors for the StringTokenizer class.
Constructor | Purpose |
StringTokenizer(String) | Creates a new StringTokenizer based on the specified string to be tokenized. |
StringTokenizer(String, String) | Creates a new StringTokenizer based on the specified string to be tokenized and set of delimiters. |
StringTokenizer(String,String,
boolean) | Creates a new StringTokenizer based on the specified string to be tokenized, set of delimiters, and a flag that indicates if delimiters should be returned as tokens. |
Because StringTokenizer implements the enumeration interface it includes the hasMoreElements and nextElement methods. Additionally, the methodshasMoreTokens and nextToken are provided and perform the same operations. The nonprivate methods of StringTokenizer are summarized in Table 11.14.
Table 11.14. Nonprivate methods of the StringTokenizer class.
Method | Purpose |
countTokens() | Returns the number of remaining tokens. |
hasMoreElements() | Returns true if there are more elements in the string being tokenized. It is identical tohasMoreTokens. |
hasMoreTokens() | Returns true if there are more tokens in the string being tokenized. It is identical tohasMoreElements. |
nextElement() | Returns the next element in the string. It is identical to nextToken. |
nextToken() | Returns the next token in the string. It is identical to nextElement. |
nextToken(String) | Changes the set of delimiters to the specified string and then returns the next token in the string. |
Class EX11H is an example of how to use the StringTokenizer class and is shown in Listing 11.8. In this example two StringTokenizer objects are created. The first,st1, is used to parse an arithmetic expression. The second, st2, parses a line of comma-delimited fields. For both tokenizers, hasMoreTokens and nextToken are used to iterate through the set of tokens, displaying each token in a TextArea. The results of executing EX11H are shown in Figure 11.6.
import java.applet.*;
import java.awt.*;
import java.util.*;
public class EX11H extends Applet
{
TextArea results = new TextArea(14, 25);
public void init()
{
resize(320, 240);
add(results);
// put an arithmetic expression in a string
// and create a tokenizer for the string
String mathExpr = "4*3+2/4";
StringTokenizer st1 = new StringTokenizer(mathExpr,
"*+/-", true);
// while there are tokens left, display each token
results.appendText("Tokens of mathExpr:\r\n");
while (st1.hasMoreTokens())
results.appendText(st1.nextToken() + "\r\n");
// create a String of comma-delimited fields
// and create a tokenizer for the string
String commas = "field1,field2,field3,and field 4";
StringTokenizer st2=new StringTokenizer(commas,",",false);
// while there are tokens left, display each token
results.appendText("Comma-delimited tokens:\r\n");
while (st2.hasMoreTokens())
results.appendText(st2.nextToken() + "\r\n");
}
}
0 comments:
Post a Comment