More Collections Interfaces and Classes

Một phần của tài liệu Beginning Java SE 6 Platform From Novice to Professional phần 2 ppsx (Trang 30 - 37)

The java.utilpackage provides the interfaces and classes that form the collections framework. I introduce collections-oriented interfaces and classes that also support con- currency later in this chapter, in the “New and Improved Concurrency” section. Table 2-5 describes the six new interfaces and classes that Java SE 6 integrates into this package.

Method Description

Table 2-5.New java.util Package Interfaces and Classes

Interface/Class Description

Deque<E> An interface that describes a double-ended queue, a linear collection that supports the insertion and removal of elements at either end.

NavigableMap<K, V> An interface that describes an extended SortedMap<K, V>with navigation methods that return the closest matches for specific search targets.

NavigableSet<E> An interface that describes an extended

SortedSet<E>with navigation methods that return the closest matches for specific search targets.

AbstractMap.SimpleEntry<K, V> A class that implements a mutable Map.Entry<K, V>, maintaining a key and a value.

AbstractMap.SimpleImmutableEntry<K, V> A class that implements an immutable

Map.Entry<K, V>, maintaining a key and a value.

ArrayDeque<E> A class that implements Deque<E>as a resizable array. It allows efficient insertion and removal of elements at both ends, and is a great choice for stacks or queues.

The Deque<E>interface and ArrayDeque<E>implementation class are preferable to the legacy java.util.Stack<E>class when introducing a stack data structure into source code.

The fact that Stack<E>is implemented as a java.util.Vector<E>is one reason for this pref- erence. This implementation makes it easy to access Vector<E>methods that can violate the integrity of the stack, such as public void add(int index, E element). To use a deque as a stack, Deque<E>provides void addFirst(E e), E removeFirst(), and E peekFirst() methods. These methods correspond to the Stack<E>class’s E push(E item), E pop(), and E peek()methods.

One application that benefits from a stack is a postfix calculator, which requires an operator’s operands to be specified before the operator. For example, 10.5 30.2 +is a postfix expression that sums 10.5 and 30.2. The source code for a postfix calculator application that uses Deque<E>and ArrayDeque<E>for its stack is presented in Listing 2-8.

Listing 2-8.PostfixCalc.java // PostfixCalc.java import java.io.*;

import java.util.*;

public class PostfixCalc {

public static void main (String [] args) throws IOError {

Console console = System.console ();

if (console == null) {

System.err.println ("unable to obtain console");

return;

}

console.printf ("Postfix expression Calculator\n\n");

console.printf ("Valid operators: + - * /\n");

console.printf ("Valid commands: c/C (clear stack), "+

"t/t (view stack top)\n\n");

Deque<Double> stack = new ArrayDeque<Double> ();

loop:

while (true) {

String line = console.readLine (">").trim ();

switch (line.charAt (0)) {

case 'Q':

case 'q': break loop;

case 'C':

case 'c': while (stack.peekFirst () != null) stack.removeFirst ();

break;

case 'T':

case 't': console.printf ("%f\n", stack.peekFirst ());

break;

case '+': if (stack.size () < 2) {

console.printf ("missing operand\n");

break;

}

double op2 = stack.removeFirst ();

double op1 = stack.removeFirst ();

double res = op1+op2;

console.printf ("%f+%f=%f\n", op1, op2, res);

stack.addFirst (res);

break;

case '-': if (stack.size () < 2) {

console.printf ("missing operand\n");

break;

}

op2 = stack.removeFirst ();

op1 = stack.removeFirst ();

res = op1-op2;

console.printf ("%f-%f=%f\n", op1, op2, res);

stack.addFirst (res);

break;

case '*': if (stack.size () < 2) {

console.printf ("missing operand\n");

break;

}

op2 = stack.removeFirst ();

op1 = stack.removeFirst ();

res = op1*op2;

console.printf ("%f*%f=%f\n", op1, op2, res);

stack.addFirst (res);

break;

case '/': if (stack.size () < 2) {

console.printf ("missing operand\n");

break;

}

op2 = stack.removeFirst ();

op1 = stack.removeFirst ();

res = op1/op2;

console.printf ("%f/%f=%f\n", op1, op2, res);

stack.addFirst (res);

break;

default : try {

stack.addFirst (Double.parseDouble (line));

}

catch (NumberFormatException nfe) {

console.printf ("double value expected\n");

} }

} } }

When you run this application, you will be prompted to enter a line of input. Enter an operator (+, -, *, or /), a number operand, or a command (c/C, t/T, or q/Q), but only one of these items. Before entering an operator, remember that you need at least two operands on the stack. Here is an example:

>10

>20

>+

10.000000+20.000000=30.000000

>q

Note The LinkedList<E>class has been reworked to implement Deque<E>.

The NavigableMap<K, V>and NavigableSet<E>interfaces provide methods that return a map view based on a range of keys and a set view based on a range of entries. For example, because the TreeMap<K, V>and TreeSet<E>classes have been retrofitted to implement these interfaces, the following TreeMap<K, V>method returns a TreeMap<K, V>-backed view that presents a range of the map’s keys:

public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive)

and the following TreeSet<E>method returns a TreeMap<E>-backed view that presents a range of the set’s entries:

public NavigableSet<E> subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive)

Listing 2-9 presents the source code to a product database application that demonstrates subMap()and two more new TreeMap<K, V>methods:

• SortedMap<K,V> headMap(K toKey), which returns a map view whose keys are less than toKey

• SortedMap<K,V> tailMap(K fromKey), which returns a map view whose keys are greater than or equal to fromKey

Listing 2-9.ProductDB.java //ProductDB.java

import java.util.*;

import java.util.Map;

public class ProductDB {

public static void build (Map<Integer, Product> map) {

map.put (1000, new Product ("DVD player", 350));

map.put (1011, new Product ("10 kilo bag of potatoes", 15.75));

map.put (1102, new Product ("Magazine", 8.50));

map.put (2023, new Product ("Automobile", 18500));

map.put (2034, new Product ("Towel", 9.99));

}

public static void main(String[] args) {

TreeMap<Integer, Product> db = new TreeMap<Integer, Product> ();

build (db);

System.out.println ("Database view of products ranging from 1000-1999");

System.out.println (db.subMap (1000, 1999)+"\n");

System.out.println ("Database view of products >= 1011");

System.out.println (db.tailMap (1011)+"\n");

System.out.println ("Database view of products < 2023");

System.out.println (db.headMap (2023));

} }

class Product {

String desc;

double price;

Product (String desc, double price) {

this.desc = desc;

this.price = price;

}

public String toString () {

return "Description="+desc+", Price="+price;

} }

When you run this application, you will discover the following:

• db.subMap (1000, 1999)returns a view that identifies products whose keys are 1000, 1011, and 1102.

• db.tailMap (1011)returns a view that identifies products whose keys are 1011, 1102, 2023, and 2034.

• db.headMap (2023)returns a view that identifies products whose keys are 1000, 1011, and 1102.

Note Check out Java Boutique’s “SortedSet and SortedMap Made Easier with Two New Mustang Interfaces” article (http://javaboutique.internet.com/tutorials/mustang/index.html) for a complete look at the NavigableMap<K,V>and NavigableSet<E>methods.

Một phần của tài liệu Beginning Java SE 6 Platform From Novice to Professional phần 2 ppsx (Trang 30 - 37)

Tải bản đầy đủ (PDF)

(51 trang)