This preview shows page 1. Sign up to view the full content.
Unformatted text preview: C H A P T E R 4 Lists CONTENTS Specifications for the ADT List
Refining the Specifications
Using the ADT List
Java Class Library: The Interface List
Using a List Is Like Using a Vending Machine
Appendix B Java Classes
Exception Handling OBJECTIVES After studying this chapter, you should be able to
G Describe the concept of an abstract data type (ADT)
Describe the ADT list
Use the ADT list in a Java program T his chapter builds on the concepts of encapsulation and data abstraction that were
presented in the previous chapter, and it develops the notion of an abstract data type,
or ADT. As an example of an abstract data type, we specify and use the ADT list. In
doing so we will provide a Java interface for our list. Knowing just this interface, you
will be able to use a list in a Java program. You do not need to know how the entries in
the list are represented or how the list operations are implemented. Indeed, your
program will not depend on these speciﬁcs. As you will see, this important program
feature is what data abstraction is all about.
79 80 CHAPTER 4 Lists Speciﬁcations for the ADT List
4.1 Figure 4-1 A list provides a way to organize data. We can have to-do lists, gift lists, address lists, grocery lists,
even lists of lists. These lists provide a useful way for us to organize our lives, as illustrated in
Figure 4-1. Each list has a ﬁrst item, a last item, and usually items in between. That is, the items in
a list have a position: ﬁrst, second, and so on. An item’s position might be important to you, or it
might not. When adding an item to your list, you might always add it at the end, or you might insert
it between two other items already in the list. A to-do list I have so much to do this
weekend — I should make a list.
1. Read Chapter 4
2. Call home
3. Buy card for Sue Everyday lists such as to-do lists, gift lists, address lists, and grocery lists have entries that are
strings. What can you do to such lists?
G Typically, you add a new entry at the end of the list.
Actually, you can add a new entry anywhere: at the beginning, the end, or in between items.
You can cross out an entry—that is, remove it.
You can remove all entries.
You can replace an entry.
You can look at any entry.
You can determine whether the list contains a particular entry.
You can count the number of entries in the list.
You can determine whether the list is empty or full.
You can display all of the entries in the list. Speciﬁcations for the ADT List 81 4.2 When you work with a list, you determine where an entry is or should be. You probably are not conscious of its exact position: Is it tenth? Fourteenth? However, when your program uses a list, a convenient way to identify a particular entry is by the entry’s position within the list. It could be ﬁrst,
that is, at position 1, or second (position 2), and so on. This convention allows you to describe, or
specify, the operations on a list more precisely.
At this point, you should not be thinking about how to represent a list in your program or how
to implement its operations. For the moment, forget about arrays, for example. You ﬁrst need to
clearly know what the list operations do: Focus on what the operations do, not on how they do
them. That is, you need a detailed set of speciﬁcations before you can use a list in a program. In
fact, you should specify the list operations before you even decide on a programming language.
At this point, the list is an abstract data type. An abstract data type, or ADT, consists of data
having the same type and the operations on that data. An ADT describes its data and speciﬁes its
operations. It does not indicate how to store the data or how to implement the operations. Thus, we
can discuss ADTs independently of a programming language. In contrast, a data structure is an
implementation of an ADT within a programming language. 4.3 To specify the ADT list, we describe its data and specify the operations on that data. Unlike common lists whose entries are strings, the ADT list is more general and has entries that are objects of
the same type. The following is a speciﬁcation of the ADT list: ABSTRACT DATA TYPE LIST
G A collection of objects in a speciﬁc order and having the same data type
The number of objects in the collection OPERATIONS
add(newEntry) Task: Adds newEntry to the end of the list.
Input: newEntry is an object.
Output: None. add(newPosition, newEntry) Task: Adds newEntry at position newPosition within the list.
Input: newPosition is an integer, newEntry is an object.
Output: None. remove(givenPosition) Task: Removes from the list the entry at position givenPosition.
Input: givenPosition is an integer.
Output: None. clear() Task: Removes all entries from the list.
Output: None. 82 CHAPTER 4 Lists replace(givenPosition, newEntry) Task: Replaces the entry at position givenPosition with
Input: givenPosition is an integer, newEntry is an object.
Output: None. getEntry(givenPosition) Task: Retrieves the entry at position givenPosition in the list.
Input: givenPosition is an integer.
Output: Returns a reference to the entry at position
givenPosition. contains(anEntry) Task: Determines whether the list contains anEntry.
Input: anEntry is an object.
Output: Returns true if anEntry is in the list, or false if not. getLength() Task: Gets the number of entries currently in the list.
Output: Returns the number of entries currently in the list as
an int. isEmpty() Task: Determines whether the list is empty.
Output: Returns true if the list is empty, or false if not. isFull() Task: Determines whether the list is full.
Output: Returns true if the list is full, or false if not. display() Task: Displays all entries that are in the list in the order in which
they occur, one per line.
Output: None. We have only begun to specify the behaviors of these list operations, as the speciﬁcations just
given leave some details to the imagination. Some examples will help us to better understand these
operations so that we can improve the speciﬁcations. We’ll need precise speciﬁcations before we
implement the operations. Programming Tip: After designing a draft of an ADT, conﬁrm your understanding of the
operations and their design by writing some pseudocode that uses the ADT. Speciﬁcations for the ADT List 4.4 83 Example. When you ﬁrst declare a new list, it is empty and its length is zero. If you add three
objects—a, b, and c—one at a time and in the order given, to the end of the list, the list will appear as
c The object a is ﬁrst, and c is last. To save space here, we will sometimes write a list’s contents on
one line. For example, we might write
a b c to represent this list.
The following pseudocode represents the previous three additions to the speciﬁc list myList:
myList.add(c) At this point, myList is not empty, so myList.isEmpty() is false. Since the list contains three
entries, myList.getLength() is 3. Notice that adding entries to the end of a list does not change the
positions of entries already in the list. Figure 4-2 illustrates these add operations as well as the operations that we describe next.
Figure 4-2 The effect of ADT list operations on an initially empty list
myList.add(a) myList.add(b) myList.add(c) a a
c 4.5 myList.add(1,e)
c Now suppose that we add entries at various positions within the list. For example,
myList.add(2, d) places d at position 2 within the list. Doing so, however, moves b to position 3 and c to position 4,
so that the list now contains
a d b c 84 CHAPTER 4 Lists If we add e to the beginning of the list by writing
myList.add(1, e) the current entries in the list move to the next higher position. The list then contains
e a d b c Look at Figure 4-2 again to see the effect of these operations. 4.6 We can retrieve the second entry in this list by writing
ref2 = myList.getEntry(2) This expression returns a reference to the second entry. Remember that we are writing pseudocode
here. Later examples in Java will show you that a type cast is likely to be necessary.
What happens when we remove an entry? For example,
myList.remove(3) removes the third entry—d in the previous example—from the list. The list then contains
e a b c Notice that entries after the one that was removed move to the next lower position within the
list. Figure 4-2 illustrates this change to the list.
What if an application requires us to remove an entry from a list but retain the entry for
another purpose? Our interpretation of remove would force us to ﬁrst use getEntry to obtain a reference to the entry and then use remove to remove the entry from the list. We could reﬁne the speciﬁcation of remove to return a reference to the object removed from the list. To use this version of
remove, we would write a pseudocode statement such as
ref3 = myList.remove(3) This change makes remove more versatile, as the client could either save or ignore the returned
We can replace the third entry b of our list with f by writing
myList.replace(3, f) No other entries move or change. We could reﬁne the speciﬁcation of replace to return a reference
to the object that was replaced. So if we wrote
ref = myList.replace(3, f)
ref would reference the former entry b. Note: The objects in an ADT list have an order determined by the client of the list. To add,
remove, or retrieve an entry, you must specify the entry’s position within the list. Reﬁning the Speciﬁcations
4.7 The previous speciﬁcations ignore at least three difﬁculties that might arise during the use of the
G G The operations add, remove, replace, and getEntry are well behaved when the given position
is valid for the current list. What happens when one of these operations receives an invalid
The methods remove, replace, and getEntry are not meaningful for empty lists. What
happens when an empty list invokes one of these operations? Speciﬁcations for the ADT List G 85 A list could become full, depending on the list’s implementation. What happens when the client
tries to add an entry to a full list? You as class designer need to make decisions about how to handle unusual conditions and include
these decisions in your speciﬁcations. The documentation for the ADT list should reﬂect both these
decisions and the detail that the previous examples demonstrate. 4.8 In general, you can address unusual situations in several ways. Your method could
G Assume that the invalid situations will not occur. This assumption is not as naive as it might
sound. A method could state as an assumption—that is, a precondition—restrictions to which a
client must adhere. It is then up to the client to enforce the precondition by checking that the
precondition is satisﬁed before invoking the method. Notice that the client has methods such as
isEmpty and getLength to help with this task. As long as the client obeys the restriction, the
invalid situation will not occur.
Ignore the invalid situations. A method could simply do nothing when given invalid data.
Doing absolutely nothing, however, leaves the client wondering what happened.
Make reasonable assumptions and act in a predictable way. For example, if a client tries to
remove the sixth entry from a three-entry list, the remove method could either remove the last
entry instead or return null.
Return a boolean value that indicates the success or failure of an operation.
Throw an exception. As Appendix B shows, throwing an exception is often a desirable way for a Java method to
react to unusual events that occur during its execution. The method can simply report a problem
without deciding what to do about it. The exception enables each client to do what is needed in its
own particular situation. To handle errors in this way, you must write try-catch blocks to use the
method. For simplicity, we adopt the philosophy that methods should throw exceptions only in truly
exceptional circumstances, when no other reasonable solution exists. Future chapters will include
some examples of handling exceptions. 4.9 After you have identiﬁed all unusual circumstances, you should specify how your methods will
behave under each of these circumstances. For example, it would be reasonable for the add method
to throw an exception if it tries to add an entry at an invalid position. However, it might be just as
reasonable for the method to return false in these situations.
Your documentation for your ADT should describe these speciﬁcations. As your speciﬁcations
become more detailed, they increasingly should reﬂect your choice of programming language. Ultimately, you can write a Java interface (see Chapter 3) for the class that will implement the ADT. Note: A ﬁrst draft of an ADT’s speciﬁcations often overlooks or ignores situations that you really need to consider. You might intentionally make these omissions to simplify this ﬁrst draft.
Once you have written the major portions of the speciﬁcations, you can concentrate on the
details that make the speciﬁcations complete. 4.10 The following Java interface contains the methods for an ADT list and detailed comments that
describe their behaviors. Recall that a class interface does not include data ﬁelds, constructors, private methods, or protected methods. We assume that items in the list will be objects—that is,
instances of a class. For example, we could have a list of strings. To accommodate entries of any
class type, the list methods use Object as the type of entry. As we discussed previously, all classes
ultimately are derived from Object. 86 CHAPTER 4 Lists For lists of primitive types, we could replace each occurrence of Object with the desired type.
Another possibility, however, would be to place instances of an appropriate wrapper class in our
list. For example, instead of instances of the primitive type int, we could use instances of the wrapper class Integer. (Appendix A discusses wrapper classes.)
/** An interface for the ADT list.
* Entries in the list have positions that begin with 1.
public interface ListInterface
/** Task: Adds a new entry to the end of the list.
* @param newEntry the object to be added as a new entry
* @return true if the addition is successful, or false if not */
public boolean add(Object newEntry);
/** Task: Adds a new entry at a specified position within
the list. Entries originally at and above the specified
position are at the next higher position within the list.
The list’s size is increased by 1.
* @param newPosition an integer that specifies the desired
position of the new entry; newPosition >= 1
and newPosition <= getLength()+1
* @param newEntry
the object to be added as a new entry
* @return true if the addition is successful, or false if not */
public boolean add(int newPosition, Object newEntry);
/** Task: Removes the entry at a given position from the list.
Entries originally at positions higher than the given
position are at the next lower position within the list,
and the list’s size is decreased by 1.
* @param givenPosition an integer that indicates the position of
the entry to be removed; givenPosition >= 1
and givenPosition <= getLength()
* @return either the entry at position givenPosition, if the removal
was successful, or null */
public Object remove(int givenPosition);
/** Task: Removes all entries from the list. */
public void clear();
/** Task: Replaces the entry at a given position in the list.
* @param givenPosition an integer that indicates the position of the
entry to be replaced; givenPosition >= 1
and givenPosition <= getLength()
* @param newEntry the object that will replace the entry at the
* @return true if the replacement occurs, or false if either the
list was empty or givenPosition is invalid */
public boolean replace(int givenPosition, Object newEntry);
/** Task: Retrieves the entry at a given position in the list.
* @param givenPosition an integer that indicates the position of
the desired entry; givenPosition >= 1
and givenPosition <= getLength()
* @return a reference to the indicated list entry, if found, Speciﬁcations for the ADT List 87 *
otherwise returns null */
public Object getEntry(int givenPosition);
/** Task: Determines whether the list contains a given entry.
* @param anEntry the object that is the desired entry
* @return true if the list contains anEntry, or false if not */
public boolean contains(Object anEntry);
/** Task: Gets the length of the list.
* @return the integer number of entries currently in the list */
public int getLength();
/** Task: Determines whether the list is empty.
* @return true if the list is empty, or false if not */
public boolean isEmpty();
/** Task: Determines whether the list is full.
* @return true if the list is full, or false if not */
public boolean isFull();
/** Task: Displays all entries that are in the list, one per
line, in the order in which they occur in the list. */
public void display();
} // end ListInterface Question 1 Write pseudocode statements that add some objects to a list, as follows. First
add c, then a, then b, and then d such that the order of the objects in the list will be a, b, c, d.
Question 2 Write pseudocode statements that exchange the third and seventh entries in a
list of ten objects. Note: The entries in a list of n entries are numbered from 1 to n. Although you cannot add a
new entry at position 0, you can add one at position n + 1. 4.11 After specifying an ADT and writing a Java interface for its operations, you should write some Java
statements that use the ADT. In this way, you check both the suitability and your understanding of
the speciﬁcations. It is better to revise the design or documentation of the ADT now instead of after
you have written its implementation. An added beneﬁt of doing this task carefully is that you can
use these same Java statements later to test your implementation.
The following section looks at several examples that use a list. These examples can be part of a
program that tests your implementation. Programming Tip: Write a test program before you implement a class Writing Java statements that test a class’s methods will help you to fully understand the
speciﬁcations for the methods. Obviously, you must understand a method before you can
implement it correctly. If you are also the class designer, your use of the class might help you
see desirable changes to your design or its documentation. You will save time if you make
these revisions before you have implemented the class. Since you must write a program that
tests your implementation sometime, why not get additional beneﬁts from the task by writing
it now instead of later? 88 CHAPTER 4 Lists Using the ADT List
Imagine that we hire a programmer to implement the ADT list in Java, given the interface and speciﬁcations that we have developed so far. If we assume that these speciﬁcations are clear enough for
the programmer to complete the implementation, we can use the ADT’s operations in a program
without knowing the details of the implementation. That is, we do not need to know how the programmer implemented the list to be able to use it. We only need to know what the ADT list does.
This section assumes that we have an implementation for the list and demonstrates how we can
use a list in our program. 4.12 Figure 4-3 Example. Imagine that we are organizing a local road race. Our job is to note the order in which the
runners ﬁnish the race. Since each runner wears a distinct identifying number, we can add each runner’s number to the end of a list as the runners cross the ﬁnish line. Figure 4-3 illustrates such a list. A list of numbers that identify runners in the order in which they ﬁnished a race 16
27 The following Java program shows how we can perform this task by using the ADT list. It
assumes that the class AList implements the Java interface ListInterface that you saw in the previous section. Since ListInterface assumes that the items in the list are objects, we will treat each
runner’s identifying number as a string.
public class ListClient
public static void main(String args)
} // end main
public static void testList()
ListInterface runnerList = new AList(); // has only methods
// in ListInterface
runnerList.add("16"); // winner
runnerList.add(" 4"); // second place Using the ADT List 89 runnerList.add("33"); // third place
runnerList.add("27"); // fourth place
} // end testList
} // end ListClient The output from this program is
Notice that the data type of runnerList is ListInterface instead of AList. While either type
is correct, using ListInterface obliges runnerList to call only methods in the interface. 4.13 Example. The previous example uses the list method display to display the items in the list. We
might want our output in a different form, however. The following method is an example of how a
client could display the items in a list without using the method display. Notice the use of the list
methods getLength and getEntry. Also notice that the data type of the input parameter aList is
ListInterface. Thus, we can use as the argument of the method an instance of any class that
implements ListInterface. That is, the method works for any implementation of the ADT list.
public static void displayList(ListInterface aList)
int numberOfEntries = aList.getLength();
System.out.println("The list contains " + numberOfEntries +
" entries, as follows:");
for (int position = 1; position <= numberOfEntries; position++)
" is entry " + position);
} // end displayList Assuming the list runnerList from the example in Segment 4.12, the expression
produces the following output: display- List(runnerList) The list contains 4 entries, as follows:
16 is entry 1
4 is entry 2
33 is entry 3
27 is entry 4 4.14 Example. A professor wants an alphabetical list of the names of the students who arrive for class
today. As each student enters the room, the professor adds the student’s name to a list. It is up to the
professor to place each name into its correct position in the list so that the names will be in alphabetical order. The ADT list does not choose the order of its entries.
The following Java statements place the names Amy, Ellen, Bob, Drew, Aaron, and Carol in an
alphabetical list. The comment at the end of each statement shows the list after the statement executes.
// make an alphabetical list of the names
// Amy, Ellen, Bob, Drew, Aaron, Carol
ListInterface alphaList = new AList(); 90 CHAPTER 4 Lists
Amy Bob Ellen
Amy Bob Drew Ellen
Aaron Amy Bob Drew Ellen
Aaron Amy Bob Carol Drew Ellen After initially adding Amy to the beginning of the list and Ellen to the end of the list (at position 2), the professor inserts
G Bob between Amy and Ellen at position 2
Drew between Bob and Ellen at position 3
Aaron before Amy at position 1
Carol between Bob and Drew at position 4 This technique of inserting each name into a collection of alphabetized names is called an insertion
sort. We will discuss this and other ways of ordering items in a later chapter.
If we now remove the entry at position 4—Carol—by writing
alphaList.remove(4); Drew and Ellen will then be at positions 4 and 5, respectively. Thus, alphaList.getEntry(4)
would return a reference to Drew.
Finally, suppose that we want to replace a name in this list. We cannot replace a name with just
any name and expect that the list will remain in alphabetical order. Replacing Bob with Ben by
alphaList.replace(3, "Ben"); would maintain alphabetical order, but replacing Bob with Nancy would not. The list’s alphabetical
order resulted from our original decisions about where to add names to the list. The order did not
come about automatically as a result of list operations. That is, the client, not the list, maintained
the order. We could, however, design an ADT that maintains its data in alphabetical order. You will
see an example of such an ADT in Chapter 13.
Question 3 Suppose that alphaList contains a list of the four strings Amy, Ellen, Bob,
and Drew. Write Java statements that swap Ellen and Bob and that then swap Ellen and
Drew so that the list will be in alphabetical order. 4.15 Example. Let’s look at a list of objects that are not strings. Suppose that we have the class Name
from Chapter 1 that represents a person’s ﬁrst and last names. The following statements indicate
how we could make a list of the names Amy Smith, Tina Drexel, and Robert Jones:
// make a list of names as you think of them
ListInterface nameList = new AList();
Name amy = new Name("Amy", "Smith");
nameList.add(new Name("Tina", "Drexel");
nameList.add(new Name("Robert", "Jones"); Now let’s retrieve the name that is second in the list:
Name secondName = (Name)nameList.getEntry(2); Notice that we must type-cast the object that getEntry returns. To accommodate entries of any
class type, the list methods use Object as the type of entry. In particular, the return type of getEntry is Object. Thus, we must type-cast the returned entry to the data type of the entries in the list.
That type is Name in this example. Java Class Library: The Interface List 91 Earlier we said that an ADT has data of the same type. As you will see in the next chapters, the
implementations of the ADT list will not enforce this requirement. As this example just showed,
you must know the data type of an entry in a list when you retrieve or remove it so that you can perform any necessary type cast. Although Java will let you place objects of various types in the same
list, you would need to keep track of their data types. In general, requiring an ADT’s entries to have
the same type makes life easier. Programming Tip: Type-cast returned objects ADT entries that a method returns are of type Object and must be type-cast to their actual type.
b. 4.16 The example in Segment 4.13 used getEntry to retrieve an entry from a list. Why was a type cast to String not necessary?
Would a type cast to String be wrong? Example. Let’s talk a bit more about the previous example. The variable secondName is a reference
to the second object of type Name in the list. Using this reference, we can modify the object. For
example, we could change its last name by writing
secondName.setLast("Doe"); If the class Name did not have set methods like setLast, we would be unable to modify the objects
in this list. For instance, if we had a list of strings, we would not be able to alter one of the strings in this
way. Once we create an object of the class String, we cannot alter it. We could, however, replace an
entire object in the list—regardless of its type—by using the ADT list operation replace.
A class, such as Name, that has set methods is a class of mutable objects. A class, such as
String, without set methods is a class of immutable objects. Chapter 15 talks about such classes
in more detail. Java Class Library: The Interface List
4.17 The standard package java.util contains an interface for the ADT list that is similar to our interface. Its name is List. The major difference between a list in the Java Class Library and our ADT
list is the numbering of a list’s entries. A list in the Java Class Library uses the same numbering
scheme as a Java array: The ﬁrst entry is at position, or index, 0. In contrast, we begin our list at
The interface List also declares more methods than our interface does. The following method
signatures are for a selection of methods that are similar to the ones you have seen in this chapter.
We have used blue to indicate where they differ from our methods.
public boolean add(Object newEntry)
void add(int index, Object newEntry)
Object remove(int index)
Object set(int index, Object anEntry) // like replace
Object get(int index)
// like getEntry
boolean contains(Object anEntry)
// like getLength
boolean isEmpty() The second add method is a void method. It throws an exception if index is out of range, instead of
returning a boolean value, as our add method does. The method set is like our replace method, but 92 CHAPTER 4 Lists it returns a reference to the entry that was replaced in the list instead of returning a boolean value.
The other differences are simply in the method names used. For example, the interface List uses
get for our getEntry and size for our getLength.
You can learn more about the interface List at
http://java.sun.com/products/jdk/1.4/docs/api/index.html Using a List Is Like Using a Vending Machine
Figure 4-4 Imagine that you are in front of a vending machine, as Figure 4-4 depicts; better yet, take a break
and go buy something from one! A vending machine I’m really
thirsty—where is that
vending machine? When you look at the front of a vending machine, you see its interface. By inserting coins and
pressing buttons, you are able to make a purchase. Here are some observations that we can make
about the vending machine:
G You can perform only the speciﬁc tasks that the machine’s interface presents to you.
You must understand these tasks—that is, you must know what to do to buy a soda.
You cannot see or access the inside of the machine, because a steel shell encapsulates it.
You can use the machine even though you do not know what happens inside.
If someone replaced the machine’s inner mechanism with an improved version, leaving the
interface unchanged, you could still use the machine in the same way. You, as the user of a vending machine, are like the client of the ADT list that you saw earlier in
this chapter. The observations that we just made about the user of a vending machine are similar to
the following observations about a list’s client:
G The client can perform only the operations speciﬁc to the ADT list. These operations often are
declared within a Java interface. Using a List Is Like Using a Vending Machine G
G 4.19 C HAPTER S UMMARY 93 The client must adhere to the speciﬁcations of the operations that the ADT list provides. That
is, the author of the client must understand how to use these operations.
The client cannot access the data within the list without using an ADT operation. The principle
of encapsulation hides the data within the ADT.
The client can use the list, even though it cannot access the list’s entries directly—that is, even
though the programmer does not know how the data is stored.
If someone changed the implementation of the list’s operations, the client could still use the list
in the same way, as long as the interface did not change. In the examples of the previous section, each list is an instance of a class that implements the ADT
list. That is, each list is an object whose behaviors are the operations of the ADT list. You can think
of each such object as the vending machine that we just described. Each object encapsulates the
list’s data and operations just as the vending machine encapsulates its product (soda cans) and
Some ADT operations have inputs analogous to the coins you insert into a vending machine.
Some ADT operations have outputs analogous to the change, soda cans, messages, and warning
lights that a vending machine provides.
Now imagine that you are the designer of the front, or interface, of the vending machine. What
can the machine do, and what should a person do to use the machine? Will it help you or hinder you
to think about how the soda cans will be stored and transported within the machine? We maintain
that you should ignore these aspects and focus solely on how to use the machine—that is, on your
design of the interface. Ignoring extraneous details makes your task easier and increases the quality
of your design.
Recall that abstraction as a design principle asks you to focus on what instead of how. When
you design an ADT, and ultimately a class, you use data abstraction to focus on what you want to
do with or to the data without worrying about how you will accomplish these tasks. We practiced
data abstraction at the beginning of this chapter when we designed the ADT list. We referred to
each entry in our list by its position within the list. As we chose the methods that a list would have,
we did not consider how we would represent the list. Instead, we focused on what each method
Ultimately, we wrote a Java interface that speciﬁed the methods in detail. We were then able to
write a client that used the list, again without knowledge of its implementation. If someone wrote
the implementation for us, our program would presumably run correctly. If someone else gave us a
better implementation, we could use it without changing our already-written client. This feature of
the client is a major advantage of abstraction. G An abstract data type, or ADT, consists of both data and a set of operations on the data. An ADT provides a way to design a new data type independently of the choice of programming language. G A list is an ADT whose data consists of ordered entries. Each entry is identiﬁed by its position within the
list. G A Java program manipulates or accesses a list’s entries by using only the operations deﬁned for the ADT
list. The manifestation of the ADT in a programming language encapsulates the data and operations.
That is, the particular data representations and method implementations are hidden from the client. G When you use data abstraction to design an ADT, you focus on what you want to do with or to the data
without worrying about how you will accomplish these tasks. That is, you ignore the details of how you
represent data and how you manipulate it. 94 CHAPTER 4 Lists P ROGRAMMING T IPS After designing a draft of an ADT, conﬁrm your understanding of the operations and their design by
writing some pseudocode that uses the ADT. G After specifying an ADT and writing a Java interface for its operations, write some Java statements that
use the ADT. In this way, you check both the suitability and your understanding of the speciﬁcations. An
added beneﬁt of doing this task carefully is that later you can use these same Java statements to test
your implementation. G E XERCISES G ADT entries that a method returns are of type Object and must be type-cast to their actual type. 1. If myList is an empty list, what does it contain after the following statements execute?
myList.replace(3, "delta"); 2. Suppose that you want an operation for the ADT list that removes the ﬁrst occurrence of
a given object from the list. The signature of the method could be as follows:
public boolean remove(Object anObject) Write comments that specify this method.
3. Write Java statements at the client level that return the position of a given object in the
list myList. Assume that the object is in the list.
4. Suppose that you want an operation for the ADT list that returns the position of a given
object in the list. The signature of the method could be as follows:
public int getPosition(Object anObject) Write comments that specify this method.
5. Suppose that the ADT list did not have a method replace. Write Java statements at the
client level that replace an object in the list nameList. The object’s position in the list is
givenPosition and the replacement object is newObject.
6. Suppose that the ADT list did not have a method contains. Suppose further that
nameList is a list of Name objects, where Name is as deﬁned in Chapter 1. Write Java
statements at the client level that determine whether the Name object myName is in the list
7. Suppose that you have a list that is created by the following statement:
ListInterface studentList = new AList(); Imagine that someone has added to the list several instances of the class Student that
Chapter 2 deﬁned.
a. Write Java statements that display the last names of the students in the list in the same
order in which the students appear in the list. Do not alter the list.
b. Write Java statements that interchange the ﬁrst and last students in the list. Using a List Is Like Using a Vending Machine 95 8. Consider a class Coin that represents a coin. The class has methods such as getValue,
toss, and isHeads. The method getValue returns the value, or denomination, of a coin.
The method toss simulates a coin toss in which the coin lands either heads up or tails
up. The method isHeads returns true if a coin is heads up.
Suppose that coinList is an ADT list of coins that have randomly selected
denominations. Toss each of these coins. If the result of a coin toss is heads, move the
coin to a second list called headsList; if it is tails, leave the coin in the original list.
When you are ﬁnished tossing coins, compute the total value of the coins that came up
heads. Assume that the list headsList has been created for you and is empty initially. P ROJECTS 1. The introduction to this book spoke of a bag as a way to organize data. A grocery bag,
for example, contains items in no particular order. Some of them might be duplicate
items. The ADT bag, like the grocery bag, is perhaps the simplest of data organizations.
It holds objects but does not arrange or organize them further.
Design an ADT bag. Many operations are analogous to those of the ADT list, but
the entries do not have positions. In addition to these basic operations, include the
G A union operation that combines the contents of two bags into a third bag
An intersection operation that creates a bag of those items that occur in both of
A difference operation that creates a bag of the items that would be left in one
bag after removing those that also occur in another bag Specify each ADT operation by stating its purpose, by describing its parameters, and by
writing preconditions, postconditions, and a pseudocode version of its signature. Then
write a Java interface for the ADT bag that includes javadoc-style comments.
2. You might have a piggy bank or some other receptacle to hold your spare coins. The
piggy bank holds the coins but gives them no other organization. And certainly the bank
can contain duplicate coins. The piggy bank is like the ADT bag that you designed in
Project 1, but it is simpler. It has only three operations: You can add a coin to the bank,
remove one (you shake the bank, so you have no control over what coin falls out), or
determine whether the bank is empty.
Design the ADT piggy bank, assuming that you have the ADT bag from Project 1
and the class Coin from Exercise 8. Write a Java interface for the ADT piggy bank that
includes javadoc-style comments.
3. Santa Claus allegedly keeps lists of those who are naughty and those who are nice. On
the naughty list are the names of those who will get coal in their stockings. On the nice
list are those who will receive gifts. Each object in this list contains a name (an instance
of Name, as deﬁned in Chapter 1) and a list of that person’s gifts (an instance of an ADT
Design an ADT for the objects in the nice list. What operations should this ADT
have? After you design the ADT, implement it by writing a Java class. Assume that you
have an implementation of the ADT list—that is, assume that the class AList implements
ListInterface, as given in this chapter. Finally, create some instances of your class and
place them on Santa’s nice list. 96 CHAPTER 4 Lists 4. A recipe contains a title, a list of ingredients, and a list of directions. An entry in the list
of ingredients contains an amount, a unit, and a description. For example, 2 cups of ﬂour
could be an entry in this list.
Implement a class of recipes, assuming that the class AList implements
ListInterface, as given in this chapter. The amount of an ingredient can be a double
value or an instance of the class MixedNumber, which was described in Project 3 of
Chapter 3. ...
View Full Document
This note was uploaded on 04/29/2010 for the course CS 5503 taught by Professor Kaylor during the Spring '10 term at W. Alabama.
- Spring '10
- Computer Science