Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Java How to Program, Fourth Edition - Deitel H., Deitel P.pdf
Скачиваний:
58
Добавлен:
24.05.2014
Размер:
14.17 Mб
Скачать

1226

Collections

Chapter 21

48

49 } // end class SortedSetTest

set:

black green grey orange red tan white yellow

headSet ("orange"): black green grey

tailSet ("orange"): orange red tan white yellow first: black

last : yellow

Fig. 21.12 Using SortedSets and TreeSets.

Line 14 constructs a TreeSet object containing the elements of names and assigns a reference to this object to tree. Line 21 calls method headSet to get a subset of the TreeSet less than "orange". Any changes made to the subset are made to the TreeSet (i.e., the subset returned is a view of the TreeSet). Line 25 calls method tailSet to get a subset greater than or equal to "orange". Like headSet, any changes made through the tailSet view are made to the TreeSet. Lines 28–29 call methods first and last to get the smallest and largest elements, respectively.

Programmer-defined method printSet (lines 33–41) takes a SortedSet (e.g., a TreeSet) as an argument and prints it. Line 35 gets an Iterator for the Set. The body of the while loop prints each element of the SortedSet.

21.8 Maps

Maps associate keys to values and cannot contain duplicate keys (i.e., each key can map to only one value; this type of mapping is called one-to-one mapping). Maps differ from Sets in that Maps contain keys and values, whereas Sets contain only keys. Classes HashMap and TreeMap implement the Map interface. HashMaps store elements in HashTables, and TreeMaps store elements in trees. Interface SortedMap extends Map and maintains its keys in sorted order (i.e., the elements’ natural order or an order, specified by a Comparator). Class TreeMap implements SortedMap.

Figure 21.13 uses a HashMap to count the number of Strings that begin with a given letter. [Note: Unlike class Hashtable, class HashMap allows a null key and null values].

1// Fig. 21.13: MapTest.java

2 // Using a HashMap to store the number of words that 3 // begin with a given letter

4

5 // Java core packages

6 import java.util.*;

7

8public class MapTest {

9

private static String names[] = { "one", "two", "three",

10

"four", "five", "six", "seven", "two", "ten", "four" };

 

 

Fig. 21.13

Using HashMaps and Maps (part 1 of 2).

© Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

Chapter 21

Collections

1227

11

12// build a HashMap and output contents

13public MapTest()

14{

15HashMap map = new HashMap();

16Integer i;

17

 

18

for ( int count = 0; count < names.length; count++ ) {

19

i = ( Integer ) map.get(

20

new Character( names[ count ].charAt( 0 ) ) );

21

 

22

// if key is not in map then give it value one

23

// otherwise increment its value by 1

24

if ( i == null )

25

map.put(

26

new Character( names[ count ].charAt( 0 ) ),

27

new Integer( 1 ) );

28

else

29

map.put(

30

new Character( names[ count ].charAt( 0 ) ),

31

new Integer( i.intValue() + 1 ) );

32

}

33

 

34

System.out.println(

35"\nnumber of words beginning with each letter: " );

36printMap( map );

37}

38

39// output map contents

40public void printMap( Map mapRef )

41{

42System.out.println( mapRef.toString() );

43System.out.println( "size: " + mapRef.size() );

44System.out.println( "isEmpty: " + mapRef.isEmpty() );

45}

46

47// execute application

48public static void main( String args[] )

49{

50new MapTest();

51}

52

53 } // end class MapTest

number of words beginning with each letter: {t=4, s=2, o=1, f=3}

size: 4 isEmpty: false

Fig. 21.13 Using HashMaps and Maps (part 2 of 2).

Line 15 constructs HashMap map. The for loop on lines 18–32 uses map to store the number of words in array names that begin with a given letter. Lines 19–20 call method get to retrieve a Character (the first letter of a String in names) from the

© Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

1228

Collections

Chapter 21

HashMap. If the HashMap does not contain a mapping for the Character, get returns null. If the HashMap does contain the mapping for the Character, its mapping value is returned as an Object. The returned value is cast to Integer and assigned to i.

If i is null, the Character is not in the HashMap, and lines 25–27 call method put to write an Integer containing 1 to the HashMap. The Integer value stored in the HashMap is the number of words beginning with that Character.

If the Character is in the HashMap, lines 29–31 increment the Integer counter by one and write the updated counter to the HashMap. A HashMap cannot contain duplicates, so put replaces the previous Integer object with the new one.

Programmer-defined method printMap takes one Map argument and prints it, using method toString. Lines 43–44 call methods size and isEmpty to get the number of values in the Map and a boolean indicating whether the Map is empty, respectively.

21.9 Synchronization Wrappers

In Chapter 15, we discussed multithreading. The built-in collections are unsynchronized. Concurrent access to a Collection by multiple threads could cause indeterminate results or fatal errors. To prevent potential threading problems, synchronization wrappers are used around collection classes that might be accessed by multiple threads. A wrapper class receives method calls, adds some functionality for thread safety and delegates the calls to the wrapped class.

The Collections API provides a set of public static methods for converting collections to synchronized versions. Method headers for the synchronization wrappers are listed in Fig. 21.14.

21.10 Unmodifiable Wrappers

The Collections API provides a set of public static methods for converting collections to unmodifiable versions (called unmodifiable wrappers) of those collections. Method headers for these methods are listed in Fig. 21.15. Unmodifiable wrappers throw UnsupportedOperationExceptions if attempts are made to modify the collection.

Software Engineering Observation 21.8

When creating an unmodifiable wrapper, not holding a reference to the backing collection ensures nonmodifiability.

public static method header

Collection synchronizedCollection( Collection c )

List synchronizedList( List aList )

Set synchronizedSet( Set s )

SortedSet synchronizedSortedSet( SortedSet s )

Map synchronizedMap( Map m )

SortedMap synchronizedSortedMap( SortedMap m )

Fig. 21.14 Synchronization wrapper methods.

© Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

Chapter 21 Collections 1229

public static method header

Collection unmodifiableCollection( Collection c )

List unmodifiableList( List aList )

Set unmodifiableSet( Set s )

SortedSet unmodifiableSortedSet( SortedSet s )

Map unmodifiableMap( Map m )

SortedMap unmodifiableSortedMap( SortedMap m )

Fig. 21.15 Unmodifiable wrapper methods.

Software Engineering Observation 21.9

You can use an unmodifiable wrapper to create a collection that offers read-only access to others, while allowing read–write access to yourself. You do this simply by giving others a reference to the unmodifiable wrapper while you also retain a reference to the wrapped collection itself.

21.11 Abstract Implementations

The collections framework provides various abstract implementations (i.e., “bare bones” implementations of collection interfaces from which the programmer can quickly “flesh out” complete customized implementations). These abstract implementations are a thin Collection implementation called an AbstractCollection, a thin List implementation with random-access backing called an AbstractList, a thin Map implementation called an AbstractMap, a thin List implementation with sequential-access backing called an AbstractSequentialList and a thin Set implementation called an AbstractSet.

To write a custom implementation, begin by selecting as a base the abstract-implemen- tation class that best meets your needs. Next, implement each of the class’s abstract methods. Then, if your collection is to be modifiable, override any concrete methods that prevent modification.

21.12 (Optional) Discovering Design Patterns: Design Patterns Used in Package java.util

In this section, we use the material on data structures and collections discussed in Chapters 19, 20 and 21 to identify classes from package java.util that use design patterns. This section concludes our treatment of design patterns.

21.12.1 Creational Design Patterns

We conclude the discussion of creational design patterns by discussing the Prototype design pattern.

Prototype

Sometimes, a system must make a copy of an object but will not know that object’s class until run time. For example, consider the drawing program design of Exercise 9.28—class-

© Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

1230

Collections

Chapter 21

es MyLine, MyOval and MyRect represent “shape” classes that extend abstract superclass MyShape. We could modify this exercise to allow the user to create, copy and paste new instances of class MyLine into the program. The Prototype design pattern allows an object—called a prototype—to return a copy of that prototype to a requesting object— called a client. Every prototype must belong to a class that implements a common interface that allows the prototype to clone itself. For example, the Java API provides method clone from class java.lang.Object and interface java.lang.Cloneable— any object from a class implementing Cloneable can use method clone to copy itself. Specifically, method clone creates a copy of an object, then returns a reference to that object. If we designate class MyLine as the prototype for Exercise 9.28, then class MyLine must implement interface Cloneable. To create a new line in our drawing, we clone the MyLine prototype. To copy a preexisting line, we clone that object. Method clone also is useful in methods that return a reference to an object, but the developer does not want that object to be altered through that reference—method clone returns a reference to the copy of the object instead of returning that object’s reference. For more information of interface Cloneable, visit

www.java.sun.com/j2se/1.3/docs/api/java/lang/Cloneable.html

21.12.2 Behavioral Design Patterns

We conclude the discussion of behavioral design patterns by discussing the Iterator design pattern.

Iterator

Designers use data structures such as arrays, linked lists and hash tables, to organize data in a program. The Iterator design pattern allows objects to access individual objects from any data structure without knowing the data structure’s behavior (such as traversing the structure or removing an element from that structure) or how that data structure stores objects. Instructions for traversing the data structure and accessing its elements are stored in a separate object called an iterator. Each data structure can create an iterator—each iterator implements methods of a common interface to traverse the data structure and access its data. An object can traverse two differently structured data structures—such as a linked list and a hash table—in the same manner, because both data structures contain an iterator object that belongs to a class implementing a common interface. Java provides interface Iterator from package java.util, which we discussed in Section 21.5—class

CollectionTest (Fig 21.3) uses an Iterator object.

21.12.3 Conclusion

In our optional “Discovering Design Patterns” sections, we have introduced the importance, usefulness and prevalence of design patterns. We have mentioned that in their book

Design Patterns, Elements of Reusable Object-Oriented Software, the “gang of four” described 23 design patterns that provide proven strategies for building systems. Each pattern belongs to one of three pattern categories: creational, which address issues related to object creation; structural, which provide ways to organize classes and objects in a system; and behavioral, which offer strategies to model how objects collaborate with one another in a system.

© Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

Chapter 21

Collections

1231

Of the 23 design patterns, we discussed 18 of the more popular ones used by the Java community. In Sections 9.24, 13.18, 15.13, 17.11 and 21.12, we divided the discussion according to how certain Java packages—such as package java.awt, javax.swing, java.io, java.net and java.util—use these design patterns. We also discussed patterns not described by the “gang of four,” such as concurrency patterns, which are useful in multithreaded systems, and architectural patterns, which help designers assign functionality to various subsystems in a system. We have motivated each pattern—that is, explained why that pattern is important and how it may be used. When appropriate, we supplied several examples in the form of real-world analogies (e.g., the adapter in the Adapter design pattern is similar to an adapter for a plug on an electrical device). We also gave examples of how Java packages take advantage of design patterns (e.g., Swing GUI components use the Observer design pattern to collaborate with their listeners to respond to user interactions). We also provided examples of how certain programs in Java How to Program, Fourth edition used design patterns (e.g., the elevator-simulation case study in our optional “Thinking About Objects” sections uses the State design pattern to represent a Person object’s location in the simulation).

We hope that you view our “Discovering Design Patterns” sections as a beginning to further study of design patterns. If you have not done so already, we recommend that you visit the many URLs we have provided in Section 9.24.5, Internet and World-Wide-Web Resources. We recommend that you then read the gang-of-four book. This information will help you build better systems using the collective wisdom of the object-technology industry.

If you have studied the optional sections in this book, you have been introduced to more substantial Java systems. If you have read our optional “Thinking About Objects” Sections, you have immersed yourself in a substantial design and Java implementation experience learning a disciplined approach to object-oriented design with the UML. If you have read our optional “Discovering Design Patterns” Sections, you have raised your awareness of the more advanced topic of design patterns.

We hope you continue your study of design patterns, and we would be most grateful if you would send your comments, criticisms and suggestions for improvement of Java How to Program to deitel@deitel.com. Good luck!

SUMMARY

The Java collections framework gives the programmer access to prepackaged data structures, as well as algorithms for manipulating those data structures.

Java 2 provides an entire collections framework, whereas earlier versions of Java provided just a few collection classes, like HashTable and Vector, as well as built-in array capabilities.

A collection is a data structure; actually, it is an object that can hold other objects. The collection interfaces define the operations that can be performed on each type of collection.

The collections framework includes a number of other features that minimize the amount of work programmers need to do to create and manipulate collections. This structure is an effective implementation of the notion of reuse.

The classes and interfaces that compose the collections framework are members of the java.util package.

Class Arrays provides static methods for manipulating arrays. Class Arrays methods include binarySearch for searching a sorted array, equals for comparing arrays, fill for placing items in an array, sort for sorting an array and asList.

©Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

1232

Collections

Chapter 21

Class Arrays provides method asList for getting a “List view” of the array. A List view allows the programmer to programmatically manipulate the array as if it were a List. This allows the programmer to treat an array as a collection. Any modifications made through the List view change the array, and any modifications to the array change the List view.

Method size gets the number of items in a List, and method get gets an individual List element.

Interface Collection is the root interface in the collections hierarchy from which interfaces Set and List are derived. Interface Collection contains bulk operations for adding, clearing, comparing and retaining objects in the collection.

Interface Collection provides a method iterator for getting an Iterator.

Class Collections provides static methods for manipulating collections. Many of the methods are implementations of polymorphic algorithms for searching, sorting and so on.

A List is an ordered Collection that can contain duplicate elements. A List is sometimes called a sequence.

Interface List is implemented by classes ArrayList, LinkedList and Vector. Class ArrayList is a resizable-array implementation of a List. ArrayList behavior and capabilities are similar to those of class Vector. A LinkedList is a linked-list implementation of a List.

Iterator method hasNext determines whether a Collection contains another element. Method hasNext returns true if another element exists, false otherwise. Method next returns the next object in the Collection and advances the Iterator.

Method subList gets a portion of a List, called a sublist. Any changes made to a sublist are also made to the List (i.e., the sublist is a “list view” of its corresponding List elements).

Method clear removes elements from a List.

Method toArray returns the contents of a collection as an array.

Algorithms sort, binarySearch, reverse, shuffle, fill and copy operate on Lists. Algorithms min and max operate on Collections. Algorithm reverse reverses the elements of a List, fill sets every List element to a specified Object and copy copies elements from one List into another List. Algorithm sort sorts the elements of a List.

Algorithms min and max find the smallest item and the largest item in a Collection.

The Comparator object provides a means of sorting a Collection’s elements in an order other than the Collection’s natural order.

Method reverseOrder returns a Comparator object that represents the reverse order for a collection.

Algorithm shuffle randomly orders the elements of a List.

Algorithm binarySearch locates an Object in a List.

A Set is a Collection that contains no duplicate elements. The collections framework contains two Set implementations: HashSet and TreeSet. HashSet stores its elements in a hash table; TreeSet stores its elements in a tree.

Interface SortedSet extends Set and maintains its elements in sorted order. Class TreeSet implements SortedSet.

Method headSet gets a subset of a TreeSet less than a specified element. Any changes made to the subset are made to the TreeSet. Method tailSet gets a subset greater than or equal to a specified element. Any changes made through the tailSet view are made to the TreeSet.

Maps map keys to values and cannot contain duplicate keys. Maps differ from Sets in that Maps contain both keys and the values, whereas Sets contain only keys. Classes HashMap and

©Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

Chapter 21

Collections

1233

TreeMap implement the Map interface. HashMaps store elements in a HashTable, and TreeMaps store elements in a tree.

Interface SortedMap extends Map and maintains its elements in sorted order. Class TreeMap implements SortedMap.

The built-in collections are unsynchronized. Concurrent access to a Collection by independent threads could cause indeterminate results. To prevent this, synchronization wrappers are used around classes that might be accessed by multiple threads.

The Collections API provides a set of public static methods for converting collections to unmodifiable versions. Unmodifiable wrappers throw UnsupportedOperationExceptions if attempts are made to modify the collection.

The collections framework provides various abstract implementations (i.e., “bare bones” implementations of collection interfaces from which the programmer can quickly “flesh out” complete customized implementations).

TERMINOLOGY

AbstractCollection class AbstractList class AbstractMap class AbstractSequentialList class AbstractSet class

add method addFirst method addLast method algorithms

ArrayList arrays

arrays as collections

Arrays.asList bidirectional iterator binarySearch algorithm clear method

Collection interface collections

Collections class collections framework collections placed in arrays

Comparator object copy algorithm

data structures

delete an element from a collection deque

double-ended queue (deque) duplicate elements

Enumeration interface fill algorithm

HashMap class HashSet class Hashtable class hashtable implementation

hasNext method implementation classes

insert an element into a collection interface

isEmpty method iterator

Iterator interface key

lexicographical comparison

LinkedList class

List interface

ListIterator map

Map collection interface mapping keys to values mappings

maps as collections max algorithm min algorithm

modifiable collections natural ordering next method one-to-one mapping ordered collection ordering

queue

range-view methods reverse algorithm reverseOrder method sequence

Set interface shuffle algorithm size method

sort a List

© Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

1234

Collections

Chapter 21

sort algorithm

TreeSet class

SortedMap collection interface

unmodifiable collections

SortedSet collection interface

Vector class

stable sort

 

view

synchronization wrappers

view an array as a List

TreeMap class

wrapper class

SELF-REVIEW EXERCISES

21.1Fill in the blanks in each of the following statements:

a)

Objects in a collection are called

 

.

 

 

b)

An element in a List can be accessed by using the element’s

.

c)

Lists are sometimes called

 

 

 

.

 

 

 

d)

You can use a/an

 

 

to create a collection that offers only read-only access to

 

others while allowing read–write access to yourself.

 

 

e)

 

can be used to create stacks, queues, trees and deques (double-ended

 

queues).

 

 

 

 

 

 

 

21.2State whether each of the following is true or false. If false, explain why.

a)A Set can contain duplicates.

b)A Map can contain duplicate keys.

c)A LinkedList can contain duplicates.

d)Collections is an interface.

e)Iterators can remove elements, while Enumerations cannot.

ANSWERS TO SELF-REVIEW EXERCISES

21.1a) elements. b) index. c) sequences. d) unmodifiable wrapper. e) LinkedLists.

21.2a) False. A Set cannot contain duplicate values.

b)False. A Map cannot contain duplicate keys.

c)True.

d)False. Collections is a class, and Collection is an interface.

e)True.

EXERCISES

21.3Define each of the following terms:

a)Collection

b)Collections

c)Comparator

d)List

21.4Briefly answer the following questions:

a)What is the primary difference between a Set and a Map?

b)Can a double-subscripted array be passed to Arrays method asList? If yes, how would an individual element be accessed?

c)What must you do before adding a primitive data type (e.g., double) to a collection?

21.5Explain briefly the operation of each of the following Iterator-related methods:

a)iterator

b)hasNext

c)next

© Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

Chapter 21

Collections

1235

21.6State whether each of the following is true or false. If false, explain why.

a)Elements in a Collection must be sorted in ascending order before performing a binarySearch.

b)Method first gets the first element in a TreeSet.

c)A List created with Arrays.asList is resizable.

d)Class Arrays provides static method sort for sorting array elements.

21.7Rewrite method printList of Fig. 21.4 to use a ListIterator.

21.8Rewrite lines 16–23 in Fig. 21.4 to be more concise by using the asList method and the LinkedList constructor that takes a Collection argument.

21.9Write a program that reads in a series of first names and stores them in a LinkedList. Do not store duplicate names. Allow the user to search for a first name.

21.10Modify the program of Fig. 21.13 to count the number of occurrences of all letters (e.g., five occurrences of "o" in the example). Display the results.

21.11Write a program that determines and prints the number of duplicate words in a sentence. Treat uppercase and lowercase letters the same. Ignore punctuation.

21.12Rewrite your solution to Exercise 19.8 to use a LinkedList collection.

21.13Rewrite your solution to Exercise 19.9 to use a LinkedList collection.

21.14Write a program that takes a whole-number input from a user and determines if it is prime. If the number is prime, add it to a JTextArea. If the number is not prime, display the prime factors of the number in a JLabel. Remember that a prime number’s factors are only 1 and the prime number itself. Every number that is not prime has a unique prime factorization. For example, consider the number 54. The factors of 54 are 2, 3, 3 and 3. When the values are multiplied together, the result is

54.For the number 54, the prime factors output should be 2 and 3. Use Sets as part of your solution.

21.15Rewrite your solution to Exercise 22.21 to use a LinkedList.

21.16Write a program that tokenizes (using class StreamTokenizer) a line of text input by the user and places each token in a tree. Print the elements of the sorted tree.

© Copyright 1992–2002 by Deitel & Associates, Inc. All Rights Reserved. 7/12/01

22

Java Media Framework

and Java Sound (on CD)

Objectives

To understand the capabilities of the Java Media Framework (JMF).

To understand the capabilities of the Java Sound API.

To be able to play audio and video media with JMF.

To be able to stream media over a network.

To be able to capture, format and save media.

To be able to play sounds with the Java Sound API.

To be able to play, record, and synthesize MIDI with the Java Sound API.

TV gives everyone an image, but radio gives birth to a million images in a million brains.

Peggy Noonan

Noise proves nothing. Often a hen who has merely laid an egg cackles as if she had laid an asteroid.

Mark Twain, Following the Equator

A wide screen just makes a bad film twice as bad.

Samuel Goldwyn

Isn’t life a series of images that change as they repeat themselves?

Andy Warhol

Chapter 22

Java Media Framework and Java Sound (on CD)

1237

Outline

22.1Introduction

22.2Playing Media

22.3Formatting and Saving Captured Media

22.4RTP Streaming

22.5Java Sound

22.6Playing Sampled Audio

22.7Musical Instrument Digital Interface (MIDI)

22.7.1MIDI Playback

22.7.2MIDI Recording

22.7.3MIDI Synthesis

22.8Internet and World Wide Web Resources

22.9(Optional Case Study) Thinking About Objects: Animation and Sound in the View

Summary • Terminology • Self-Review Exercises • Answers to Self-Review Exercises • Exercises

22.1 Introduction

This chapter continues our multimedia discussions of Chapter 18 by introducing some of Java’s multimedia APIs that enable programmers to enhance applications with video and audio features. In recent years, the digital multimedia sector of the computer industry has experienced tremendous growth, as evidenced by the enormous quantity of multimedia content available on the Internet. Web sites have been transformed from text-based HTML pages to multimedia-intensive experiences. Advances in hardware and software technologies have allowed developers to integrate multimedia into the simplest applications. At the high end of multimedia applications, the video game industry has used multimedia programming to take advantage of the latest hardware technologies, such as 3D video cards that create virtual reality experiences for users.

Acknowledging that Java applications should support digital video and audio capabilities, Sun Microsystems, Intel and Silicon Graphics worked together to produce a multimedia API known as the Java Media Framework (JMF). The JMF API is one of several multimedia APIs in Java. Using the JMF API, programmers can create Java applications that play, edit, stream and capture many popular media types. The first half of this chapter discusses the JMF API.

IBM and Sun developed the latest JMF specification—version 2.0. Sun provides a reference implementation—JMF 2.1.1—of the JMF specification which supports media file types such as Microsoft Audio/Video Interleave (.avi), Macromedia Flash 2 movies (.swf), Future Splash (.spl), MPEG Layer 3 Audio (.mp3), Musical Instrument Digital Interface (MIDI;.mid), MPEG-1 videos (.mpeg, .mpg), QuickTime (.mov), Sun Audio

(.au), Wave audio (.wav), AIFF (.aiff) and GSM (.gsm) files. The JMF also supports media from capture devices such as microphones and digital cameras.