Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Generics & Collections CISC6795, Spring 2011 Dr. Zhang A sideline about array An array: a sequence of either objects or primitives that are all the same type and are packaged together under one identifier name. Arrays are defined and used with the square brackets indexing operator [ ]. To define an array reference: int[] a1; //Preferred by some in Java community Or put square brackets after identifier: int a1[]; //C/C++ style The similarity between C and Java array ends here ! 2 Initializing array Unlike in C/C++, Java does not allow int a1[20]; int a1[]; // declare a reference to an array (memory is allocated for the reference), and there’s been no space allocated for the array object itself. To create storage for the array, you must write an initialization expression int[] a1 = { 1, 2, 3, 4, 5 }; Compiler allocates storage allocation (equivalent of using new) at this point. int[] a2=a1; // copying the reference, 3 Create array of primitive types import java.util.*; import static net.mindview.util.Print.*; public class ArrayNew { public static void main(String[] args) { int[] a; // a reference to an array (of integer) object Random rand = new Random(47); a = new int[rand.nextInt(20)]; // create an array of size 20 integer print("length of a = " + a.length); print(Arrays.toString(a)); } use new to create the elements in the array. } /* Output: new works even though it’s creating an array of primitives (new won’t create a non-array primitive) length of a = 18 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 4 Create array of non-primitive types If you create a non-primitive array, you create an array of references: public class Inventory { public Inventory ( ) items is only an array of references { new is called to create the array, items = new Item[5]; items[0] = new Item (1, "MEDIUM_PIZZA“, 1239, 0.0,10); items[1] = new Item (2, "LARGE_PIZZA“, 1598, 0.0, 10); reference itself is initialized by creating a new Item object 5 Outline: next two lessons Generics, new feature of J2SE 5.0 Provide compile-time type safety: catch invalid types at compile time Generic methods: A single method declaration => a set of methods Generic interfaces: A single interface declaration => a set of interface Generic classes: A single class declaration => a set of classes Java collections framework Contain prepackaged data structures, interfaces, algorithms Use existing data structures Example of code reuse Provides reusable components 6 Motivation for Generic Methods Overloaded methods Similar methods perform same operations on different types of data Overloaded printArray methods to print: Integer array Double array Character array Only reference types can be used with generic methods/classes Type-wrapper classes in package java.lang Enable programmers to manipulate primitive-type values as objects Boolean, Byte, Character, Double, Float, Integer, Long and Short 7 Autoboxing and Auto-Unboxing Boxing conversion Converts a value of a primitive type to an object of the corresponding type-wrapper class From int to Integer, double to Double … Unboxing conversion Converts an object of a type-wrapper class to a value of the corresponding primitive type From Long to long, Float to float J2SE 5.0 automatically performs these conversions Called autoboxing and auto-unboxing 8 1 // Fig. 18.1: OverloadedMethods.java 2 // Using overloaded methods to print array of different types. 3 Outline 4 public class OverloadedMethods 5 6 { 7 8 9 10 // method printArray to print Integer array public static void printArray( Integer[] inputArray ) { // display array elements Method printArray for ( Integer element : inputArray ) System.out.printf( "%s ", element ); 11 12 13 9 System.out.println(); 14 15 16 17 } // end method printArray 18 19 20 21 { 22 23 24 25 accepts an array of Integer objects // method printArray to print Double array public static void printArray( Double[] inputArray ) // display array elements for ( Double element : inputArray ) System.out.printf( "%s ", element ); System.out.println(); } // end method printArray Method printArray accepts an array of Double objects 10 26 // method printArray to print Character array 27 public static void printArray( Character[] inputArray ) 28 { Outline 29 // display array elements 30 for ( Character element : inputArray ) Method printArray accepts an array of Character objects System.out.printf( "%s ", element ); 31 32 System.out.println(); 33 34 } // end method printArray 35 36 public static void main( String args[] ) 37 { 38 // create arrays of Integer, Double and Character 39 Integer[] integerArray = { 1, 2, 3, 4, 5, 6 }; 40 Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 }; 41 Character[] characterArray = { 'H', 'E', 'L', 'L', 'O' }; 42 Auto-boxing happens here… System.out.println( "Array integerArray contains:" ); 43 45 Outline 46 printArray( doubleArray ); // pass a Double array 47 System.out.println( "\nArray characterArray contains:" ); 48 printArray( characterArray ); // pass a Character array printArray( integerArray ); // pass an Integer array 44 System.out.println( "\nArray doubleArray contains:" ); } // end main 49 50 } // end class OverloadedMethods Array integerArray contains: 1 2 3 4 5 6 Array doubleArray contains: 1.1 2.2 3.3 4.4 5.5 6.6 7.7 Array characterArray contains: H E L L O 11 At compile time, compiler determines argument integerArray’s type (i.e., Integer[]), attempts to locate a method named printArray that specifies a single Integer[] parameter (lines 7-14) Motivation for Generic Methods (Cont.) The three printArray methods Array element type appears in two location Method header for statement header Combine three printArray methods into one Replace element types with a generic name E Declare one printArray method Display string representation of the elements of any array 12 Towards generic method 1 public static void printArray( E[] inputArray ) 2 { 3 // display array elements 4 for ( E element : inputArray ) 5 Replace the element type with a single generic type E System.out.printf( "%s ", element ); 6 7 System.out.println(); 8 } // end method printArray Actual syntax: public static < E > void printArrays( E[] array) Type parameter section, also called formal type parameters Delimited by angle brackets ( < and > ) Precede the method’s return type Contain one or more type parameters 13 Generic Methods: type parameter Type parameter, also known as type variable An identifier that specifies a generic type name Act as placeholders for the types of the argument passed to the generic method, i.e., actual type arguments Usually use a capital letter Convention: use E (element) for a type parameter that represents the type of an element in an array (or other collection) Can be used in return type, parameter types and local variable types Can be declared only once but can appear more than once: public static < E > void printTwoArrays( E[] array1, E[] array2 ) 14 1 2 // Fig. 18.3: GenericMethodTest.java // Using generic methods to print array of different types. 3 4 public class GenericMethodTest 5 { Use the type parameter to declare method printArray’s parameter type // generic method printArray public static < E > void printArray( E[] inputArray ) { Type parameter section delimited // display array elements by angle brackets (< and > ) for ( E element : inputArray ) 6 7 8 9 10 System.out.printf( "%s ", element ); 11 12 13 System.out.println(); } // end method printArray 14 15 16 17 18 19 20 21 22 Use the type parameter to declare method printArray’s local variable type public static void main( String args[] ) { // create arrays of Integer, Double and Character Integer[] intArray = { 1, 2, 3, 4, 5 }; Double[] doubleArray = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7 }; Character[] charArray = { 'H', 'E', 'L', 'L', 'O' }; 15 23 System.out.println( "Array integerArray contains:" ); 24 printArray( integerArray ); // pass an Integer array 25 System.out.println( "\nArray doubleArray contains:" ); 26 printArray( doubleArray ); // pass a Double array 27 System.out.println( "\nArray characterArray contains:" ); 28 printArray( characterArray ); // pass a Character array 29 Invoke generic method printArray with an Integer array } // end main 30 } // end class GenericMethodTest Array integerArray contains: 1 2 3 4 5 6 Array doubleArray contains: 1.1 2.2 3.3 4.4 5.5 6.6 7.7 Array characterArray contains: H E L L O 16 Invoke generic method printArray with a Character array Questions/Exercises A generic method that find the maximum value in an array? Problem: need to make sure the type is comparable… Objects o1, and o2 of the type can be compared, using o1.compareTo (o2) … Need to say the type is any type that provides compareTo() method Interface ? But the parameter of compareTo is type specific, … => generic interface, an parameterized interface 17 Outline Generics, new feature of J2SE 5.0 Provide compile-time type safety: catch invalid types at compile time Generic methods: A single method declaration => a set of related methods Generic interface: a single interface declaration=> a set of related interface Generic classes: A single class declaration => a set of related classes Java collections framework, use generics Contain prepackaged data structures, interfaces, algorithms Use existing data structures Example of code reuse 18 Provides reusable components Generic Interface: Comparable public interface Comparable<T> { int compareTo(T other); } compareTo(): Compare two objects (this and other) of type T Return 0 if two objects are equal Return -1 if this is less than other Return 1 if this is greater than other imposes a total ordering, or natural ordering on the objects of each class that implements it. natural ordering is consistent with equals if and only if: (e1.compareTo(e2) == 0) <=> e1.equals(e2) for every e1 and e2 of class C. 19 Generic Interface: Comparable public interface Comparable<T> { int compareTo(T o); } Lists (and arrays) of objects that implement this interface can be sorted using Collections.sort (and Arrays.sort). Objects that implement this interface can be used as keys in a sorted map or elements in a sorted set 20 Upper bound of type parameter Next example, generic method maximum (x,y,z) Call compareTo method to compare two objects Actual type must implement Comparable interface 21 1 // Fig. 18.5: MaximumTest.java 2 3 4 // Generic method maximum returns the largest of three objects. 5 { public class MaximumTest Type parameter is used in the return type of method maximum // determines the largest of three Comparable objects public static < T extends Comparable< T > > T maximum( T x, T y, T z ) { T max = x; // assume x is initially the largest 6 7 8 9 only object of classes that implement interface Comparable can be used 10 11 12 if ( y.compareTo( max ) > 0 ) max = y; // y is the largest so far 13 14 if ( z.compareTo( max ) > 0 ) 15 16 17 18 max = z; // z is the largest Invokes method compareTo method Comparable to compare z and max return max; // returns the largest object } // end method maximum 19 Generic interface: with a single interface declaration, a set of related types E.g., Comparable< T >, all types that implement interface Comparable 22 Outline 20 public static void main( String args[] ) 21 { 22 23 24 25 26 27 System.out.printf( "Maximum of %d, %d and %d is %d\n\n", 3, 4, 5, maximum( 3, 4, 5 ) ); System.out.printf( "Maximum of %.1f, %.1f and %.1f is %.1f\n\n", 6.6, 8.8, 7.7, maximum( 6.6, 8.8, 7.7 ) ); System.out.printf( "Maximum of %s, %s and %s is %s\n", "pear", "apple", "orange", maximum( "pear", "apple", "orange" ) ); 28 } // end main 29 } // end class MaximumTest Maximum of 3, 4 and 5 is 5 Maximum of 6.6, 8.8 and 7.7 is 8.8 Maximum of pear, apple and orange is pear 23 Invoke generic method maximum with three strings Compile-Time Translation Upper bound of type parameter: constraints on actual type Default is Object use keyword extends to specify E.g., T extends Comparable< T > When compiler translates generic method to Java bytecode Replaces type parameter with its upper bound Insert explicit cast operation e.g., line 23 of Fig. 18.5 I preceded by an Integer cast (Integer) maximum( 3, 4, 5 ) 24 Erasure 1 public static void printArray( Object[] inputArray ) 2 { 3 // display array elements 4 for ( Object element : inputArray ) System.out.printf( "%s ", element ); 5 6 System.out.println(); 7 8 } // end method printArray 1 public static Comparable maximum(Comparable x, Comparable y, Comparable z) 2 { 3 Comparable max = x; // assume x is initially the largest 4 5 6 if ( y.compareTo( max ) > 0 ) max = y; // y is the largest so far 7 8 9 if ( z.compareTo( max ) > 0 ) max = z; // z is the largest 10 11 return max; // returns the largest object 25 12 } // end method maximum Erasure replaces type parameter T with its upper bound Comparable Overloading Generic Method Generic method may be overloaded By another generic method Same method name but different method parameters By non-generic methods Same method name and number of parameters When compiler encounters a method call Search for most precise matching method first Exact method name and argument types Then search for inexact but applicable matching method Exercise: Write a generic method bubbleSort based on your lab3 26 Outline Generics, new feature of J2SE 5.0 Provide compile-time type safety: catch invalid types at compile time Generic methods: A single method declaration => a set of related methods Generic classes: A single class declaration => a set of related classes Java collections framework, use generics Contain prepackaged data structures, interfaces, algorithms Use existing data structures Example of code reuse Provides reusable components 27 Generic Classes Generic classes, parameterized classes, also called parameterized types Generic class declaration, looks like a non-generic class declaration, except class name is followed by a type parameter section a simple, concise notation to indicate the actual type(s) We study generic class Stack that implements basic stack operations: push a new element onto stack, pop an element from stack,…, independent of the actual element type Instantiate a stack of different element type: e.g., Stack< Double >, Stack<Integer>, Stack<Item> 28 1 2 3 4 // Fig. 18.7: Stack.java // Generic class Stack. public class Stack< E > 5 { 6 7 8 9 10 11 Generic class declaration, class name is followed by a type parameter section private final int size; // number of elements in the stack private int top; // location of the top element private E[] elements; // array that stores stack elements Declareaelements andefault array // no-argument constructor creates stack of as the size that stores objects of type E public Stack() { 12 13 14 this( 10 ); // default stack size } // end no-argument Stack constructor 15 16 17 18 19 20 21 // constructor creates a stack of the specified number of elements public Stack( int s ) { size = s > 0 ? s : 10; // set size of Stack top = -1; // Stack initially empty elements = ( E[] ) new Object[ size ]; // create array } // end Stack constructor 22 23 24 29 Create an array of type E. The generic mechanism does not allow type parameter in array-creation expressions because the type parameter is not available at runtime 25 26 27 28 29 Outline // push element onto stack; if successful, return true; // otherwise, throw FullStackException public void push( E pushValue ) { if ( top == size - 1 ) // if stack is full throw new FullStackException( String.format( "Stack is full, cannot push %s", pushValue ) ); 30 31 32 33 34 Method push pushes element of type E onto stack elements[ ++top ] = pushValue; // place pushValue on Stack } // end method push 35 36 37 // return the top element if not empty; else throw EmptyStackException public E pop() 38 39 40 41 { Method pop returns the top element, which is of type E if ( top == -1 ) // if stack is empty throw new EmptyStackException( "Stack is empty, cannot pop" ); 42 return elements[ top-- ]; // remove and return top element of Stack 43 } // end method pop 44 } // end class Stack< E > 30 1 // Fig. 18.8: FullStackException.java 2 // Indicates a stack is full. 3 public class FullStackException extends RuntimeException 4 { 5 6 // no-argument constructor public FullStackException() 7 8 9 { this( "Stack is full" ); } // end no-argument FullStackException constructor 10 11 // one-argument constructor 12 13 14 public FullStackException( String exception ) { super( exception ); 15 } // end one-argument FullStackException constructor 16 } // end class FullStackException 31 1 // Fig. 18.9: EmptyStackException.java 2 // Indicates a stack is full. 3 public class EmptyStackException extends RuntimeException 4 { Outline 5 // no-argument constructor 6 public EmptyStackException() 7 { 8 9 this( "Stack is empty" ); } // end no-argument EmptyStackException constructor 10 11 // one-argument constructor 12 13 14 public EmptyStackException( String exception ) { super( exception ); 15 } // end one-argument EmptyStackException constructor 16 } // end class EmptyStackException 32 Generic Classes (Cont.) Generic class at compilation time Compiler performs erasure on class’s type parameters Compiler replaces type parameters with their upper bounds Generic class test program at compilation time Compiler performs type checking Compiler inserts cast operations as necessary 33 1 2 // Fig. 18.10: StackTest.java // Stack generic class test program. 3 4 5 6 7 8 9 10 11 public class StackTest { private double[] doubleElements = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 }; private int[] integerElements = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; Generic class Stack’s type private Stack< Double > doubleStack; // stack stores Double objects argument is Double private Stack< Integer > integerStack; // stack stores Integer objects 12 // test Stack objects 13 public void testStacks() 14 { Generic class Stack’s type argument is Integer 15 16 17 doubleStack = new Stack< Double >( 5 ); // Stack of Doubles integerStack = new Stack< Integer >( 10 ); // Stack of Integers 18 19 20 21 testPushDouble(); // push double onto doubleStack size 5 and ingeterStack testPopDouble(); // pop from doubleStack testPushInteger(); // push int onto intStack testPopInteger(); // pop from intStack 22 23 3 4 Instantiate object doubleStack of of size 10 } // end method testStacks // test push method with double stack public void testPushDouble() 26 27 { // push elements onto stack 28 try 29 { 30 31 32 System.out.println( "\nPushing elements onto doubleStack" ); 33 34 35 36 for ( double element : doubleElements ) { System.out.printf( "%.1f ", element ); doubleStack.push( element ); // push onto doubleStack 37 38 39 40 41 42 43 44 45 3 5 Outline 24 25 // push elements to Stack Invoke Stack’s method push to place value onto doubleStack } // end for a double } // end try catch ( FullStackException fullStackException ) { System.err.println(); fullStackException.printStackTrace(); } // end catch FullStackException } // end method testPushDouble 46 // test pop method with double stack 47 public void testPopDouble() 48 { 49 // pop elements from stack 50 51 52 53 try { System.out.println( "\nPopping elements from doubleStack" ); double popValue; // store element removed from stack 54 55 // remove all elements from Stack 56 57 while ( true ) { popValue = doubleStack.pop(); // pop from doubleStack 58 59 60 61 62 System.out.printf( "%.1f ", popValue ); } // end while Auto-unboxing occurs when the value } // end try returned by pop (Double) is assigned catch( EmptyStackException emptyStackException ) to a double primitive variable 63 64 65 66 { 67 68 3 6 System.err.println(); emptyStackException.printStackTrace(); } // end catch EmptyStackException } // end method testPopDouble 69 70 // test push method with integer stack public void testPushInteger() 71 { 72 // push elements to stack 73 try 74 75 76 77 78 79 80 81 { 82 83 84 85 86 87 88 89 90 3 7 Outline System.out.println( "\nPushing elements onto intStack" ); // push elements to Stack for ( int element : integerElements ) { System.out.printf( "%d ", element ); integerStack.push( element ); // push onto integerStack } // end for Invoke Stack’s method push to place an int value onto integerStack } // end try catch ( FullStackException fullStackException ) { System.err.println(); fullStackException.printStackTrace(); } // end catch FullStackException } // end method testPushInteger 91 92 93 94 95 96 // test pop method with integer stack public void testPopInteger() Outline { // pop elements from stack try { 97 98 99 100 System.out.println( "\nPopping elements from intStack" ); int popValue; // store element removed from stack 101 102 while ( true ) { // remove all elements from Stack popValue = integerStack.pop(); // pop from intStack System.out.printf( "%d ", popValue ); 103 104 } // end while } // end try catch( EmptyStackException emptyStackException ) { 105 106 107 108 System.err.println(); emptyStackException.printStackTrace(); 109 110 111 112 } // end catch EmptyStackException } // end method testPopInteger 113 114 public static void main( String args[] ) 115 116 { StackTest application = new StackTest(); 117 application.testStacks(); 118 } // end main 119 } // end class StackTest 38 Auto-unboxing occurs when the value returned by pop (Integer) is assigned to an int primitive variable Outline Pushing elements onto doubleStack 1.1 2.2 3.3 4.4 5.5 6.6 FullStackException: Stack is full, cannot push 6.6 at Stack.push(Stack.java:30) at StackTest.testPushDouble(StackTest.java:36) at StackTest.testStacks(StackTest.java:18) at StackTest.main(StackTest.java:117) Popping elements from doubleStack 5.5 4.4 3.3 2.2 1.1 EmptyStackException: Stack is empty, cannot pop at Stack.pop(Stack.java:40) at StackTest.testPopDouble(StackTest.java:58) at StackTest.testStacks(StackTest.java:19) at StackTest.main(StackTest.java:117) Pushing elements onto integerStack 1 2 3 4 5 6 7 8 9 10 11 FullStackException: Stack is full, cannot push 11 at Stack.push(Stack.java:30) at StackTest.testPushInteger(StackTest.java:81) at StackTest.testStacks(StackTest.java:20) at StackTest.main(StackTest.java:117) Popping elements from integerStack 10 9 8 7 6 5 4 3 2 1 EmptyStackException: Stack is empty, cannot pop at Stack.pop(Stack.java:40) at StackTest.testPopInteger(StackTest.java:103) at StackTest.testStacks(StackTest.java:21) at StackTest.main(StackTest.java:117) 39 Generic Classes (Cont.) Creating generic methods to test class Stack< E > Method testPush Perform same tasks as testPushDouble and testPushInteger Method testPop Perform same tasks as testPopDouble and testPopInteger 40 Outline 4 5 6 7 8 public class StackTest2 { private Double[] doubleElements = { 1.1, 2.2, 3.3, 4.4, 5.5, 6.6 }; private Integer[] integerElements = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 }; 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 41 // Fig. 18.11: StackTest2.java // Stack generic class test program. 1 2 3 private Stack< Double > doubleStack; // stack stores Double objects private Stack< Integer > integerStack; // stack stores Integer objects // test Stack objects public void testStacks() { doubleStack = new Stack< Double >( 5 ); // Stack of Doubles integerStack = new Stack< Integer >( 10 ); // Stack of Integers testPush( "doubleStack", doubleStack, doubleElements ); testPop( "doubleStack", doubleStack ); testPush( "integerStack", integerStack, integerElements ); testPop( "integerStack", integerStack ); } // end method testStacks Invoke generic methods testPush and testPop to push elements onto stack and pop elements from stack 42 25 26 27 28 29 30 31 32 Outline // generic method testPush pushes elements onto a Stack public < T > void testPush( String name, Stack< T > stack, T[] elements ) { Generic method testPush replaces // push elements onto stack testPushDouble and testPushInteger try { System.out.printf( "\nPushing elements onto %s\n", name ); 33 34 35 36 // push elements onto Stack for ( T element : elements ) { System.out.printf( "%s ", element ); stack.push( element ); // push element onto stack 37 38 39 40 41 } with type } // end try catch ( FullStackException fullStackException ) 42 { 43 44 45 46 47 Replace element type Double/Integer parameter T System.out.println(); fullStackException.printStackTrace(); } // end catch FullStackException } // end method testPush 48 49 // generic method testPop pops elements from a Stack public < T > void testPop( String name, Stack< T > stack ) 50 { 51 52 53 54 55 56 // pop elements from stack try { Outline System.out.printf( "\nPopping elements from %s\n", name ); T popValue; // store element removed from stack type Double/Integer with type parameter T 57 Replace // remove elements from element Stack 58 59 60 61 while ( true ) { popValue = stack.pop(); // pop from stack System.out.printf( "%s ", popValue ); } // end while } // end try catch( EmptyStackException emptyStackException ) { 62 63 64 65 System.out.println(); emptyStackException.printStackTrace(); 66 67 68 69 } // end catch EmptyStackException } // end method testPop 70 71 public static void main( String args[] ) 72 73 { StackTest2 application = new StackTest2(); 74 application.testStacks(); 75 } // end main 76 } // end class StackTest2 43 Generic method testPop replaces testPopDouble and testPopInteger Pushing elements onto doubleStack 1.1 2.2 3.3 4.4 5.5 6.6 FullStackException: Stack is full, cannot push 6.6 at Stack.push(Stack.java:30) at StackTest2.testPush(StackTest2.java:38) at StackTest2.testStacks(StackTest2.java:19) at StackTest2.main(StackTest2.java:74) Outline Popping elements from doubleStack 5.5 4.4 3.3 2.2 1.1 EmptyStackException: Stack is empty, cannot pop at Stack.pop(Stack.java:40) at StackTest2.testPop(StackTest2.java:60) at StackTest2.testStacks(StackTest2.java:20) at StackTest2.main(StackTest2.java:74) Pushing elements onto integerStack 1 2 3 4 5 6 7 8 9 10 11 FullStackException: Stack is full, cannot push 11 at Stack.push(Stack.java:30) at StackTest2.testPush(StackTest2.java:38) at StackTest2.testStacks(StackTest2.java:21) at StackTest2.main(StackTest2.java:74) Popping elements from integerStack 10 9 8 7 6 5 4 3 2 1 EmptyStackException: Stack is empty, cannot pop at Stack.pop(Stack.java:40) at StackTest2.testPop(StackTest2.java:60) at StackTest2.testStacks(StackTest2.java:22) at StackTest2.main(StackTest2.java:74) 44 Outline Generics, new feature of J2SE 5.0 Provide compile-time type safety: catch invalid types at compile time Generic methods: A single method declaration => a set of related methods Generic classes: A single class declaration => a set of related classes Data Structure: linked list Java collections framework, use generics Contain prepackaged data structures, interfaces, algorithms Use existing data structures Example of code reuse 45 Provides reusable components Primer on Data structure * 46 How to store a collection of data Array: fixed-size data structure for holding reference to objects with same type cannot grow and shrink at execution time Dynamic data structure: Linked list: collection of data items that link up in a chain Tree: collection of data items that form a tree 47 Linked list Self-referential class: contains an instance variable that refers to another object of the same class type, called a link Drawn as an line with arrow pointing to the other object A null reference indicates that the link does not refer to another object (drawn as a backslash in diagram) Diagram of a linked list 48 data link 1 2 3 // Fig. 17.3: List.java // ListNode and List class definitions. package com.deitel.jhtp6.ch17; 4 5 6 7 8 9 List.java // class to represent one node in a list Field data can refer to any object class ListNode (1 of 6) { // package access members; List can access these directly Object data; Stores a reference to the next ListNode object in the linked list 10 11 ListNode nextNode; 12 // constructor creates a ListNode that refers to object 13 14 15 ListNode( Object object ) { this( object, null ); 16 17 } // end ListNode one-argument constructor 18 19 20 21 // constructor creates ListNode that refers to // Object and to next ListNode ListNode( Object object, ListNode node ) { 22 23 24 49 25 data = object; nextNode = node; } // end ListNode two-argument constructor 26 // return reference to data in node 27 Object getObject() 28 { 29 return data; // return Object in this node 30 31 } // end method getObject List.java 32 33 34 35 // return reference to next node in list ListNode getNext() { return nextNode; // get next node 36 } // end method getNext 37 } // end class ListNode 38 39 // class List definition 40 public class List 50 Outline (2 of 6) References to the first and last ListNodes in a List 41 { 42 43 44 45 private ListNode firstNode; private ListNode lastNode; private String name; // string like "list" used in printing 46 47 48 // constructor creates empty List with "list" as the name public List() { 49 50 51 this( "list" ); } // end List no-argument constructor Call one-argument constructor 51 52 53 // constructor creates an empty List with a name public List( String listName ) 54 { 55 name = listName; 56 firstNode = lastNode = null; Initialize both references to null List.java 57 58 59 60 } // end List one-argument constructor 61 62 { 63 64 65 66 67 68 69 firstNode = lastNode = new ListNode( insertItem ); else // firstNode refers to new node firstNode = new ListNode( insertItem, firstNode ); } // end method insertAtFront 70 71 72 73 74 75 76 { (3 of 6) // insert Object at front of List public void insertAtFront( Object insertItem ) if ( isEmpty() ) // firstNode and lastNode refer to same object // insert Object at end of List public void insertAtBack( Object insertItem ) if ( isEmpty() ) // firstNode and lastNode refer to same Object firstNode = lastNode = new ListNode( insertItem ); else // lastNode's nextNode refers to new node lastNode = lastNode.nextNode = new ListNode( insertItem ); } // end method insertAtBack Order of evaluation? 77 78 // remove first node from List public Object removeFromFront() throws EmptyListException 79 { 80 throw new EmptyListException( name ); List.java 81 82 83 84 85 Object removedItem = firstNode.data; // retrieve data being removed 86 87 if ( firstNode == lastNode ) firstNode = lastNode = null; 88 else 89 90 91 firstNode = firstNode.nextNode; return removedItem; // return removed node data } // end method removeFromFront 94 // remove last node from List 95 96 97 public Object removeFromBack() throws EmptyListException { if ( isEmpty() ) // throw exception if List is empty 100 101 (4 of 6) // update references firstNode and lastNode 92 93 98 99 52 if ( isEmpty() ) // throw exception if List is empty throw new EmptyListException( name ); Object removedItem = lastNode.data; // retrieve data being removed 102 103 // update references firstNode and lastNode if ( firstNode == lastNode ) 104 105 106 firstNode = lastNode = null; else // locate new last node { 107 ListNode current = firstNode; 108 109 // loop while current node does not refer to lastNode 110 111 while ( current.nextNode != lastNode ) current = current.nextNode; 112 113 114 115 Outline List.java (5 of 6) lastNode = current; // current is new lastNode current.nextNode = null; } // end else 116 117 118 119 return removedItem; // return removed node data } // end method removeFromBack 120 121 122 123 // determine whether list is empty Predicate method that determines public boolean isEmpty() whether the list is empty { return firstNode == null; // return true if List is empty 124 125 } // end method isEmpty 53 126 127 // output List contents public void print() 128 129 130 { Display the list’s contents if ( isEmpty() ) { List.java System.out.printf( "Empty %s\n", name ); 131 132 133 Outline return; } // end if (6 of 6) 134 135 136 137 System.out.printf( "The %s is: ", name ); ListNode current = firstNode; 138 // while not at end of list, output current node's data 139 while ( current != null ) 140 { Output a string representation of current.data 141 System.out.printf( "%s ", current.data ); 142 current = current.nextNode; 143 } // end while 144 145 System.out.println( "\n" ); 146 } // end method print 147 } // end class List 54 Move to the next node in the list 1 // Fig. 17.4: EmptyListException.java 2 // Class EmptyListException definition. 3 package com.deitel.jhtp6.ch17; 4 5 public class EmptyListException extends RuntimeException 6 { An unchecked exception EmptyListE 7 8 // no-argument constructor public EmptyListException() 9 { 10 11 this( "List" ); // call other EmptyListException constructor } // end EmptyListException no-argument constructor 12 13 14 // one-argument constructor public EmptyListException( String name ) 15 { 16 17 super( name + " is empty" ); // call superclass constructor } // end EmptyListException one-argument constructor 18 } // end class EmptyListException 55 xception.jav a 1 // Fig. 17.5: ListTest.java 2 // ListTest class to demonstrate List capabilities. 3 import com.deitel.jhtp6.ch17.List; 4 5 import com.deitel.jhtp6.ch17.EmptyListException; 6 7 8 public class ListTest { public static void main( String args[] ) 9 10 Outline { List list = new List(); // create the List container 11 12 // insert integers in list 13 14 list.insertAtFront( -1 ); list.print(); 15 list.insertAtFront( 0 ); 16 17 list.print(); list.insertAtBack( 1 ); 18 19 20 21 list.print(); list.insertAtBack( 5 ); list.print(); 56 22 23 // remove objects from list; print after each removal try 24 { 25 Object removedObject = list.removeFromFront(); 26 27 System.out.printf( "%s removed\n", removedObject ); list.print(); 28 29 30 31 32 removedObject = list.removeFromFront(); System.out.printf( "%s removed\n", removedObject ); list.print(); 33 34 35 36 removedObject = list.removeFromBack(); System.out.printf( "%s removed\n", removedObject ); list.print(); 37 38 39 40 41 removedObject = list.removeFromBack(); System.out.printf( "%s removed\n", removedObject ); list.print(); } // end try catch ( EmptyListException emptyListException ) 42 43 44 45 { emptyListException.printStackTrace(); } // end catch } // end main 46 } // end class ListTest 57 Trees Trees: Has a single root node Each node has multiple links, each referring to a child node Left child is the root of the left subtree Right child is the root of the right subtree Siblings are the children of a specific node A leaf node has no children, i.e., null links 58 Trees (Cont.) Binary search trees Value stores in a node, Larger than values stored in its left subtree Smaller than values stored in its right subtree Searching is easy: Compare value to search for with root If smaller, goes to left subtree; if larger, goes to right subtree; if same, return found … Other algorithms: traversing a tree: inorder, preorder, postorder 59 Abstract Data Structure (ADT) Many applications need to use collections with access constraints List: a collection of data stored in certain order where insertion and deletion can be made any where in the order E.g. Insert an element at the 5th position Stack: insertion and deletion are made at one end only, i.e., top Used in compiler, operating system Queue: insertion made at one end (tail) and deletion made at another end (head) Implementation details are hidden Can use array or linked list to implement above ADT 60 Stacks Stacks, Last-in, first-out (LIFO) data structure Method push adds a new node to the top of the stack Method pop removes a node from the top of the stack and returns the data from the popped node Application example: Program execution stack Holds the return addresses , local variables and parameters of method invocation Used by the compiler to evaluate arithmetic expressions 61 Stack Implementation option 1 Stack class that inherits from List Stack methods push, pop, isEmpty and print are performed by inherited methods insertAtFront, removeFromFront, isEmpty and print push calls insertAtFront pop calls removeFromFront isEmpty and print can be called as inherited Other List methods are also inherited Including methods that should not be in the stack class’s public interface 62 Stacks implementation option 2 Stack class that contains a reference to a List Each stack method invoked delegates the call to the appropriate List method method push delegates to List method insertAtFront method pop delegates to List method removeFromFront method isEmpty delegates to List method isEmpty method print delegates to List method print Enables us to hide the List methods that should not be in our stack’s public interface 63 64 Outline 1 // Fig. 17.12: StackComposition.java 2 // Class StackComposition definition with composed List object. 3 4 package com.deitel.jhtp6.ch17; 5 6 public class StackComposition { 7 8 9 10 11 private List stackList; private List reference // no-argument constructor public StackComposition() { 12 13 14 15 16 stackList = new List( "stack" ); } // end StackComposition no-argument constructor 17 18 19 20 { // add object to stack public void push( Object object ) stackList.insertAtFront( object ); } // end method push push method delegates call to List method insertAtFront 21 22 Outline // remove object from stack public Object pop() throws EmptyListException 23 24 { 25 26 27 28 29 } // end method pop 30 return stackList.removeFromFront(); // determine if stack is empty public boolean isEmpty() { return stackList.isEmpty(); 31 } // end method isEmpty 32 33 // output stack contents 34 35 36 public void print() { stackList.print(); 37 } // end method print 38 } // end class StackComposition 65 Method pop delegates call to List method removeFromFront Method isEmpty delegates call to List method isEmpty Method print delegates call to List method print Queues Queue, First-in, first-out (FIFO) data structure Similar to a checkout line in a supermarket Enqueue: inserts nodes at the tail (or end) Dequeue: removes nodes from the head (or front) Application example: Used to support print spooling: a spooler program manages the queue of printing jobs Multi-thread programming: a pool of thread, a queue of tasks 66 Queues implementation Queue class that contains a reference to a List Method enqueue calls List method insertAtBack Method dequeue calls List method removeFromFront Method isEmpty calls List method isEmpty Method print calls List method print 67 Outline 1 2 // Fig. 17.13: Queue.java // Class Queue. 3 package com.deitel.jhtp6.ch17; 4 5 6 7 8 public class Queue { private List queueList; 9 // no-argument constructor 10 11 public Queue() { 12 13 queueList = new List( "queue" ); } // end Queue no-argument constructor 14 68 15 16 // add object to queue public void enqueue( Object object ) 17 { 18 19 20 queueList.insertAtBack( object ); } // end method enqueue An object of class List Method enqueue calls List method insertAtBack 21 // remove object from queue 22 23 24 public Object dequeue() throws EmptyListException { Method dequeue calls List return queueList.removeFromFront(); method removeFromFront 25 } // end method dequeue Outline 26 27 28 // determine if queue is empty public boolean isEmpty() 29 30 { 31 32 33 } // end method isEmpty 34 35 36 public void print() { queueList.print(); return queueList.isEmpty(); // output queue contents 37 } // end method print 38 } // end class Queue 69 Outline 1 2 // Fig. 17.14: QueueTest.java // Class QueueTest. 3 4 5 import com.deitel.jhtp6.ch17.Queue; import com.deitel.jhtp6.ch17.EmptyListException; Create a Queue 6 public class QueueTest 7 { 8 public static void main( String args[] ) 9 { Enqueue 10 Queue queue = new Queue(); 11 12 // use enqueue method 70 13 queue.enqueue( -1 ); 14 queue.print(); 15 queue.enqueue( 0 ); 16 queue.print(); 17 18 queue.enqueue( 1 ); queue.print(); 19 20 21 queue.enqueue( 5 ); queue.print(); object four integers 22 // remove objects from queue 23 try 24 { Object removedObject = null; 25 Dequeue the objects in first-in, first-out order 26 27 while ( true ) 28 { 29 removedObject = queue.dequeue(); // use dequeue method 30 System.out.printf( "%s dequeued\n", removedObject ); 31 queue.print(); } // end while 32 Display the exception’s stack trace 33 } // end try 34 catch ( EmptyListException emptyListException ) 35 { emptyListException.printStackTrace(); 36 } // end catch 37 } // end main 38 39 } // end class QueueTest 71 Outline The queue is: -1 The queue is: -1 0 The queue is: -1 0 1 The queue is: -1 0 1 5 -1 dequeued The queue is: 0 1 5 0 dequeued The queue is: 1 5 1 dequeued The queue is: 5 5 dequeued Empty queue com.deitel.jhtp6.ch17.EmptyListException: queue is empty at com.deitel.jhtp6.ch17.List.removeFromFront(List.java:81) at com.deitel.jhtp6.ch17.Queue.dequeue(Queue.java:24) at QueueTest.main(QueueTest.java:29) 72 End of primer 73 Java Collections Framework A unified architecture for representing and manipulating collections. It contains: Interfaces: abstract data types that represent collections. Interfaces allow collections to be manipulated independently of the details of their representation. Implementations: concrete implementations of collection interfaces. They are reusable data structures. Algorithms: methods that perform useful computations, such as searching and sorting, on objects that implement collection interfaces. polymorphic: same method can be used on many different implementations of the appropriate collection interface. In essence, algorithms are reusable functionality. 74 Some collection framework interfaces Java Collections Framework: enhanced with generics capabilities in J2SE 5.0 Allow one to declare a stack of Card, a queue of Customers, using the type parameter Compile-time type checking ensure only objects of given type can be stored into the collection Object retrieved from the collection is cast to appropriate type In comparison, implementation of stack/queue seen so far store a collection of Object One can store different objects into it Programmer needs to cast the object retrieved to its original type … 75 Java Collection Framework: Interfaces Hierarchy These interfaces allow collections to be manipulated independently of the details of their representation. 76 Collection Interface hierarchy Collection interface: basic functionality used by all collections, such as add and remove methods Set interface: does not allow duplicate elements useful for storing collections such as a deck of cards or student records. a subinterface, SortedSet, provides for ordering of elements List interface: an ordered collection, provides precise control over where each element is inserted or retrieved from Queue interface: additional insertion, extraction, and inspection operations. elements in a Queue are typically ordered in on a FIFO basis. 77 Collection Interface hierarchy (2) Map interface: maps keys and values similar to a Hashtable. Map's subinterface, SortedMap, maintains its key-value pairs in ascending order or in an order specified by a Comparator. 78 Collection Interfaces are generic All core collection interfaces are generic. E.g, the declaration of the Collection interface: public interface Collection<E>... The <E> syntax tells you that the interface is generic. When you declare a Collection instance you can and should specify the type of object contained in the collection. Allow compiler to verify (at compile-time) that the type of object you put into the collection is correct, reducing errors at runtime. 79 Collection Interface public interface Collection<E> extends Iterable<E> { // Basic operations int size(); boolean isEmpty(); boolean contains(Object element); boolean add(E element); //optional boolean remove(Object element); //optional 80 Collection Interface (cont’d) Return a iterator: an object for traversing through a Iterator<E> iterator(); collection and to remove elements from the collection // Bulk operations selectively boolean containsAll(Collection<?> c); boolean addAll(Collection<? extends E> c); //optional boolean removeAll(Collection<?> c); //optional boolean retainAll(Collection<?> c); //optional void clear(); //optional // Array operations Object[] toArray(); <T> T[] toArray(T[] a); } 81 General-purpose Implementations Interface Implementation Interfaces Set List Implementations Hash Resizable Tree Linked Hash table Resizable arrayHash Tree Linked table array list table+Linked list list Hash table + Linked list Set HashSet TreeSet LinkedHashSet HashSet TreeSet LinkedHashSet List ArrayList LinkedList Queue Map ArrayList LinkedList HashMap TreeMap LinkedHashMap Queue Map 82 HashMap TreeMap LinkedHashMap Lists: ordered collection List: ordered Collection that can contain duplicates Implemented via interface List ArrayList, vector ArrayList behaves like Vector without synchronization and therefore execute faster than Vectors (no overhead of thread synchronization) LinkedLists can be used to create stacks, queues, trees and deques (double-ended queues, pronounced “decks”). 83 ArrayList and Iterator ArrayList example Demonstrate Collection interface capabilities Place two String arrays in ArrayLists Use Iterator to remove elements in ArrayList 84 1 2 // Fig. 19.3: CollectionTest.java // Using the Collection interface. 3 import java.util.List; 4 5 6 7 8 import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; Outline public class CollectionTest 9 { 10 11 12 private static final String[] colors = { "MAGENTA", "RED", "WHITE", "BLUE", "CYAN" }; private static final String[] removeColors = { "RED", "WHITE", "BLUE" }; 13 14 15 16 Create ArrayList objects and assign // create ArrayList, add Colors to it and manipulate it their references to variable list and public CollectionTest() 17 { 18 19 20 85 removeList, respectively List< String > list = new ArrayList< String >(); List< String > removeList = new ArrayList< String >(); 21 // add elements in colors array to list 22 for ( String color : colors ) 23 24 25 26 27 28 29 30 add objects to list and removeList, respectively // add elements in removeColors to removeList for ( String color : removeColors ) removeList.add( color ); Get number of ArrayList elements System.out.println( "ArrayList: " ); 31 // output list contents 32 33 34 for ( int count = 0; count < list.size(); count++ ) System.out.printf( "%s ", list.get( count ) ); 35 36 37 // remove colors contained in removeList removeColors( list, removeList ); 38 System.out.println( "\n\nArrayList after calling removeColors: " ); 39 40 41 42 // output list contents for ( String color : list ) System.out.printf( "%s ", color ); 43 44 86 Outline list.add( color ); } // end CollectionTest constructor retrieve individual element values Method removeColors takes two Collections as arguments; Line 36 passes two Lists, which extends Collection, to this method 45 46 47 48 // remove colors specified in collection2 from collection1 private void removeColors( Collection< String > collection1, Collection< String > collection2 ) Outline { // get iterator Iterator< String > iterator = collection1.iterator(); 49 50 51 52 53 hasNext determines whether the Iterator contains more elements // loop while collection has items while ( iterator.hasNext() ) 54 55 Take any Collections containing strings as arguments if ( collection2.contains( iterator.next() ) ) 56 57 58 iterator.remove(); // remove current Color } // end method removeColors 59 public static void main( String args[] ) 60 { 61 62 new CollectionTest(); } // end main next returns a reference to the next element contains determines whether collection2 contains the element returned by next 63 } // end class CollectionTest ArrayList: MAGENTA RED WHITE BLUE CYAN ArrayList after calling removeColors: MAGENTA CYAN 87 Use Iterator method remove to remove String from Iterator Common Programming Error If a collection is modified by one of its methods after an iterator is created for that collection, the iterator immediately becomes invalid—any operations performed with the iterator after this point throw ConcurrentModificationExceptions. For this reason, iterators are said to be “fail fast.” 88 LinkedList LinkedList example Add elements of one List to the other Convert Strings to uppercase Delete a range of elements 89 1 // Fig. 19.4: ListTest.java 2 3 // Using LinkLists. import java.util.List; 4 5 6 import java.util.LinkedList; import java.util.ListIterator; 7 8 9 public class ListTest { private static final String colors[] = { "black", "yellow", Outline 10 11 12 "green", "blue", "violet", "silver" }; private static final String colors2[] = { "gold", "white", "brown", "blue", "gray", "silver" }; 13 14 // set up and manipulate LinkedList objects 15 public ListTest() 16 17 { List< String > list1 = new LinkedList< String >(); 18 19 20 List< String > list2 = new LinkedList< String >(); 21 22 23 for ( String color : colors ) list1.add( color ); // add elements to list link Create two LinkedList objects Use List method add to append elements from array colors to the end of list1 90 24 25 26 27 28 91 // add elements to list link2 for ( String color : colors2 ) list2.add( color ); Outline Use List method add to append elements from array colors2 to the end of list2 list1.addAll( list2 ); // concatenate lists 29 30 31 32 33 34 list2 = null; // release resources printList( list1 ); // print list1 elements Use 35 36 System.out.print( "\nDeleting elements 4 to 6..." ); removeItems( list1, 4, 7 ); // remove items 4-7 from list List method addAll to append all elements of list2 to the end of list1 convertToUppercaseStrings( list1 ); // convert to upper case string printList( list1 ); // print list1 elements 37 38 39 printList( list1 ); // print list1 elements printReversedList( list1 ); // print list in reverse order } // end ListTest constructor 40 41 // output List contents 42 43 44 45 46 47 48 public void printList( List< String > list ) { System.out.println( "\nlist: " ); 49 50 51 System.out.println(); } // end method printList for ( String color : list ) System.out.printf( "%s ", color ); Method printList allows any Lists containing strings to be passed as arguments to this method 52 53 54 55 // locate String objects and convert to uppercase private void convertToUppercaseStrings( List< String > list ) { ListIterator< String > iterator = list.listIterator(); 56 57 58 59 60 61 62 63 while ( iterator.hasNext() ) { String color = iterator.next(); // get item iterator.set( color.toUpperCase() ); // convert to upper case } // end while } // end method convertToUppercaseStrings 64 65 // obtain sublist and use clear method to delete sublist items private void removeItems( List< String > list, int start, int end ) 66 67 68 69 70 71 72 73 74 { 92 Outline list.subList( start, end ).clear(); } // end method removeItems anyitems List // remove that contains strings subList: obtain a portion of the List // print reversed list private void printReversedList( List< String > list ) { ListIterator< String > iterator = list.listIterator( list.size() ); calllistIterator with one argument (starting position) to get a bidirectional iterator 75 76 77 Outline System.out.println( "\nReversed List:" ); // print list in reverse order while ( iterator.hasPrevious() ) 78 System.out.printf( "%s ", iterator.previous() ); 79 80 hasPrevious: determine whether there are more elements while traversing the list backward } // end method printReversedList 81 82 public static void main( String args[] ) 83 { 84 85 Invoke ListIterator method previous to get the previous element from the list new ListTest(); } // end main 86 } // end class ListTest list: black yellow green blue violet silver gold white brown blue gray silver list: BLACK YELLOW GREEN BLUE VIOLET SILVER GOLD WHITE BROWN BLUE GRAY SILVER Deleting elements 4 to 6... list: BLACK YELLOW GREEN BLUE WHITE BROWN BLUE GRAY SILVER Reversed List: SILVER GRAY BLUE BROWN WHITE BLUE GREEN YELLOW BLACK 93 Sets Set interface: Collection that contains unique elements Implementations: HashSet Stores elements in hash table TreeSet Stores elements in tree Example: using HashSet to find unique elements in a collection … 94 1 // Fig. 19.18: SetTest.java 2 // Using a HashSet to remove duplicates. 3 import java.util.List; 4 5 import java.util.Arrays; import java.util.HashSet; 6 import java.util.Set; 7 8 import java.util.Collection; Outline 9 public class SetTest 10 { 11 12 13 14 15 16 17 private static final String colors[] = { "red", "white", "blue", "green", "gray", "orange", "tan", "white", "cyan", "peach", "gray", "orange" }; // create and output ArrayList public SetTest() { 18 List< String > list = Arrays.asList( colors ); 19 20 System.out.printf( "ArrayList: %s\n", list ); printNonDuplicates( list ); 21 22 95 } // end SetTest constructor Create a List that contains String objects Method printNonDuplicates accepts a Collection of type String 23 24 25 26 27 28 29 30 31 32 // create set from array to eliminate duplicates private void printNonDuplicates( Collection< String > collection ) Outline { // create a HashSet Set< String > set = new HashSet< String >( collection ); System.out.println( "\nNonduplicates are: " ); for ( String s : set ) System.out.printf( "%s ", s ); 33 34 35 36 System.out.println(); } // end method printNonDuplicates 37 38 39 40 public static void main( String args[] ) { new SetTest(); } // end main Conversion construct: create a HashSet from Collection argument 41 } // end class SetTest ArrayList: [red, white, blue, green, gray, orange, tan, white, cyan, peach, gray, orange] Nonduplicates are: red cyan white tan gray green orange blue peach 96 Software Engineering Observation Collection interface is used to pass around collections of objects where maximum generality is desired. The collection might be a linked list, an array list, a set , … E.g., All general-purpose collection implementations have a conversion constructor that takes a Collection argument. It initializes new collection to contain all elements in specified collection Next: useful Collection methods for manipulating any collections 97 How to iterate Collection for-each construct: to concisely traverse a collection or array using a for loop. for (Object o : collection) System.out.println(o); Using Iterator: an object for traversing through a collection and to remove elements from the collection selectively, if desired. Use Iterator instead of the for-each construct when you need to remove element. 98 Iterator Get an Iterator for a collection by calling its iterator method 2. Call methods of Iterator to traverse through collection 1. Iterator interface: public interface Iterator<E> { boolean hasNext(); E next(); void remove(); //optional } hasNext: returns true if iteration has more elements next: returns next element in the iteration. 99 Iterator: remove method remove: removes last element that was returned by next from underlying Collection. only safe way to modify a collection during iteration may be called only once per call to next and throws an exception if this rule is violated. behavior is unspecified if underlying collection is modified in any other way while iteration is in progress. 100 toArray method toArray: translate contents of a Collection into an array. a bridge between collections and older APIs that expect arrays on input Object[] toArray(); //creates a new array of Object. <T> T[] toArray(T[] a); //allows caller to provide an array or to choose runtime type of output array. E.g, to dump contents of a Collection c into a newly allocated array of Object Object[] a = c.toArray(); E.g., suppose that c is known to contain only string, to dumps contents of c into a newly allocated array of String: 101 String[] a = c.toArray(new String[0]); Java Collection Framework: Interfaces 102 Maps Map interface: associates keys to values, one-to-one mapping (no duplicate keys) Implementation classes Hashtable, HashMap Store elements in hash tables TreeMap Store elements in trees Interface SortedMap Extends Map Maintains its keys in sorted order 103 hash table Hash tables: data structure that use hashing, an algorithm for determining a key in table Each table cell is a hash “bucket”, i.e., linked list of all key-value pairs that hash to that cell (collision) Load factor in a hash table: average length of bucket Hash table 104 Outline 1 // Fig. 19.20: WordTypeCount.java 2 // Program counts the number of occurrences of each word in a string 3 import java.util.StringTokenizer; 4 5 import java.util.Map; import java.util.HashMap; 6 import java.util.Set; 7 8 import java.util.TreeSet; import java.util.Scanner; 9 10 public class WordTypeCount 11 { 12 13 private Map< String, Integer > map; private Scanner scanner; 14 105 Create an empty HashMap with a default capacity 16 and a default load factor 0.75. The keys are of type String and the values are of type Integer 15 16 17 18 public WordTypeCount() { map = new HashMap< String, Integer >(); // create HashMap scanner = new Scanner( System.in ); // create scanner 19 20 21 22 createMap(); // create map based on user input displayMap(); // display map content } // end WordTypeCount constructor 23 24 25 26 27 Outline { System.out.println( "Enter a string:" ); // prompt for user input String input = scanner.nextLine(); 28 29 30 31 // create StringTokenizer for input StringTokenizer tokenizer = new StringTokenizer( input ); 32 // processing input text 33 34 35 while ( tokenizer.hasMoreTokens() ) // { String word = tokenizer.nextToken().toLowerCase(); // get word containsKey: whether a key as an argument is in hash table whilespecified more input 36 37 // if the map contains the word 38 39 if ( map.containsKey( word ) ) // is word { 40 41 42 int count = map.get( word ); // get current count map.put( word, count + 1 ); // increment count } // end if 43 44 45 46 47 106 // create map from user input private void createMap() Create a StringTokenizer to break input string into individual words Use method get to obtain the key’s in map associated value in the map else map.put( word, 1 ); // add new word with a count of 1 to map } // end while } // end method createMap Increment the value and use method put to replace the key’s associated value Outline 48 // display map content 49 private void displayMap() 50 { Use HashMap method keySet to obtain a set of the keys Set< String > keys = map.keySet(); // get keys 51 52 53 // sort keys 54 TreeSet< String > sortedKeys = new TreeSet< String >( keys ); 55 System.out.println( "Map contains:\nKey\t\tValue" ); 56 57 58 // generate output for each key in map 59 for ( String key : sortedKeys ) Access each key and its value in the map System.out.printf( "%-10s%10s\n", key, map.get( key ) ); 60 61 System.out.printf( 62 "\nsize:%d\nisEmpty:%b\n", map.size(), map.isEmpty() ); 63 } // end method displayMap 64 65 Call Map method size to get the number of key-value pairs in the Map 107 Call Map method isEmpty to determine whether the Map is empty 66 67 public static void main( String args[] ) { 68 69 new WordTypeCount(); } // end main Outline 70 } // end class WordTypeCount Enter a string: To be or not to be: that is the question Whether 'tis nobler to suffer Map contains: Key Value 'tis 1 be 1 be: 1 is 1 nobler 1 not 1 or 1 question 1 suffer 1 that 1 the 1 to 3 whether 1 size:13 isEmpty:false 108 Collections algorithms Collections framework provides set of algorithms, implemented as static methods of Collections class 109 Algorithm Description sort Sorts the elements of a List. binarySearch Locates an object in a List. reverse Reverses the elements of a List. shuffle Randomly orders a List’s elements. fill Sets every List element to refer to a specified object. Copy Copies references from one List into another. min Returns the smallest element in a Collection. max Returns the largest element in a Collection. addAll Appends all elements in an array to a collection. frequency Calculates how many elements in the collection are equal to the specified element. disjoint Determines whether two collections have no elements in common. Software Engineering Observation Collections framework algorithms are polymorphic method first argument is the collection on which the operation is to be performed. majority of the algorithms operate on List instances, a few operate on arbitrary Collection instances. Each algorithm can operate on objects that implement specific interfaces, regardless of the underlying implementations. 110 Algorithm sort sort Sorts List elements Order is determined by natural order of elements’ type List elements must implement the Comparable interface Or, pass a Comparator to method sort Sorting in ascending order Collections method sort Sorting in descending order Collections static method reverseOrder Sorting with a Comparator Create a custom Comparator class 111 Example import java.util.*; public class Sort { public static void main(String[] args) { List<String> list = Arrays.asList(args); Collections.sort(list); System.out.println(list); } } 112 1 2 // Fig. 19.8: Sort1.java // Using algorithm sort. 3 import java.util.List; 4 import java.util.Arrays; 5 import java.util.Collections; 6 7 8 9 public class Sort1 { private static final String suits[] = Outline { "Hearts", "Diamonds", "Clubs", "Spades" }; 10 11 12 // display array elements 13 public void printElements() 14 15 16 { 113 List< String > list = Arrays.asList( suits ); // create List Create List of Strings 17 18 19 // output list Outline System.out.printf( "Unsorted array elements:\n%s\n", list ); Collections.sort( list ); // sort ArrayList 20 21 22 // output list 23 System.out.printf( "Sorted array elements:\n%s\n", list ); 24 } // end method printElements 25 26 public static void main( String args[] ) 27 { 28 Sort1 sort1 = new Sort1(); 29 sort1.printElements(); 30 } // end main 31 } // end class Sort1 Unsorted array elements: [Hearts, Diamonds, Clubs, Spades] Sorted array elements: [Clubs, Diamonds, Hearts, Spades] 114 Implicit call to the list’ toString method to output the list contents Use algorithm sort to order the elements of list in ascending order Outline 1 // Fig. 19.9: Sort2.java 2 3 // Using a Comparator object with algorithm sort. import java.util.List; 4 import java.util.Arrays; 5 import java.util.Collections; 6 7 public class Sort2 8 { 9 10 private static final String suits[] = { "Hearts", "Diamonds", "Clubs", "Spades" }; 11 12 // output List elements 13 14 public void printElements() { 15 16 115 List list = Arrays.asList( suits ); // create List // output List elements 17 Outline System.out.printf( "Unsorted array 18 19 Method reverseOrder of class Collections returns a Comparator object that represents elements:\n%s\n", list ); the collection’s reverse order 20 // sort in descending order using a comparator 21 Collections.sort( list, Collections.reverseOrder() ); 22 23 // output List elements 24 System.out.printf( "Sorted list elements:\n%s\n", list ); 25 } // end method printElements 26 27 public static void main( String args[] ) 28 { 29 Sort2 sort2 = new Sort2(); 30 sort2.printElements(); 31 } // end main 32 } // end class Sort2 Unsorted array elements: [Hearts, Diamonds, Clubs, Spades] Sorted list elements: [Spades, Hearts, Diamonds, Clubs] 116 Method sort of class Collections can use a Comparator object to sort a List 1 2 3 4 5 Outline import java.util.Comparator; public class TimeComparator implements Comparator< Time2 > 6 { 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 public int compare( Time2 tim1, Time2 time2 ) { int hourCompare = time1.getHour() - time2.getHour(); // compare hour // test the hour first if ( hourCompare != 0 ) return hourCompare; Implement method compare to determine the order of two Time2 objects int minuteCompare = time1.getMinute() - time2.getMinute(); // compare minute // then test the minute if ( minuteCompare != 0 ) return minuteCompare; int secondCompare = time1.getSecond() - time2.getSecond(); // compare second return secondCompare; // return result of comparing seconds } // end method compare 27 } // end class TimeComparator 117 Custom comparator TimeComparator Comparator interface and compares Time2 object // Fig. 19.10: TimeComparator.java implements // Custom Comparator class that compares two Time2 objects. 1 // Fig. 19.11: Sort3.java 2 // Sort a list using the custom Comparator class TimeComparator. 3 import java.util.List; 4 import java.util.ArrayList; 5 import java.util.Collections; Outline 6 7 8 118 public class Sort3 { 9 public void printElements() 10 { 11 12 List< Time2 > list = new ArrayList< Time2 >(); // create List 13 14 list.add( new Time2( 6, 24, 34 ) ); list.add( new Time2( 18, 14, 58 ) ); 15 16 17 18 list.add( new Time2( 6, 05, 34 ) ); list.add( new Time2( 12, 14, 58 ) ); list.add( new Time2( 6, 24, 22 ) ); 19 20 Outline // output List elements System.out.printf( "Unsorted array elements:\n%s\n", list ); 21 22 // sort in order using a comparator 23 Collections.sort( list, new TimeComparator() ); 24 25 26 // output List elements System.out.printf( "Sorted list elements:\n%s\n", list ); 27 28 29 30 } // end method printElements 31 Sort3 sort3 = new Sort3(); public static void main( String args[] ) { Sort in order using a custom comparator TimeComparator 32 sort3.printElements(); 33 } // end main 34 } // end class Sort3 Unsorted array elements: [6:24:34 AM, 6:14:58 PM, 6:05:34 AM, 12:14:58 PM, 6:24:22 AM] Sorted list elements: [6:05:34 AM, 6:24:22 AM, 6:24:34 AM, 12:14:58 PM, 6:14:58 PM] 119 Algorithms on List reverse: Reverses the order of List elements fill: populates List elements with values copy: Creates copy of a List max: Returns largest element in List min: Returns smallest element in List binarySearch: 120 Locates object in List 1 // Fig. 19.13: Algorithms1.java 2 // Using algorithms reverse, fill, copy, min and max. 3 4 5 Outline import java.util.List; import java.util.Arrays; import java.util.Collections; 6 7 public class Algorithms1 8 { 9 private Character[] letters = { ‘P’, ‘C’, ‘M’ }; 10 private Character[] lettersCopy; 11 12 private List< Character > list; private List< Character > copyList; 13 14 15 // create a List and manipulate it with methods from Collections public Algorithms1() 16 17 list = Arrays.asList( letters ); // get List 18 lettersCopy = new Character[ 3 ]; 19 20 copyList = Arrays.asList( lettersCopy ); // list view of lettersCopy 21 22 System.out.println( "Initial list: " ); output( list ); 23 24 Collections.reverse( list ); // reverse order 25 26 27 121 { Use method reverse of class Collections to obtain List in reverse order System.out.println( "\nAfter calling reverse: " ); output( list ); 28 29 30 Outline Collections.copy( copyList, list ); // copy List System.out.println( "\nAfter copying: " ); output( copyList ); Use method copy of class Collections to obtain copy of List 31 32 Collections.fill( list, ‘R’ ); // fill list with Rs 33 System.out.println( "\nAfter calling fill: " ); 34 output( list ); 35 } // end Algorithms1 constructor 36 Use method fill of class Collections to populate List with the letter ‘R’ 37 // output List information 38 private void output( List< Character > listRef ) 39 { 40 System.out.print( "The list is: " ); 41 42 43 for ( Character element : listRef ) System.out.printf( "%s ", element ); 44 45 System.out.printf( "\nMax: %s", Collections.max( listRef ) ); 46 System.out.printf( " 47 48 122 Min: %s\n", Collections.min( listRef ) ); } // end method output Obtain minimum value in List 49 50 51 52 public static void main( String args[] ) Outline { new Algorithms1(); } // end main 53 } // end class Algorithms1 Initial list: The list is: P C M Max: P Min: C After calling reverse: The list is: M C P Max: P Min: C After copying: The list is: M C P Max: P Min: C After calling fill: The list is: R R R Max: R Min: R 123 Algorithm binarySearch binarySearch locates object in List Returns index of object in List if object exists Returns negative value if Object does not exist Calculate insertion point: if the object is to be inserted into the List, where should it be inserted ? Make the insertion point sign negative Subtract 1 from insertion point (Why ?) 124 1 2 3 // Fig. 19.14: BinarySearchTest.java Outline // Using algorithm binarySearch. import java.util.List; 4 import java.util.Arrays; 5 6 import java.util.Collections; import java.util.ArrayList; 7 8 public class BinarySearchTest 9 { 10 private static final String colors[] = { "red", "white", 125 11 12 13 14 15 "blue", "black", "yellow", "purple", "tan", "pink" }; private List< String > list; // ArrayList reference 16 17 18 19 20 21 { // create, sort and output list public BinarySearchTest() list = new ArrayList< String >( Arrays.asList( colors ) ); Collections.sort( list ); // sort the ArrayList Sort List in System.out.printf( "Sorted ArrayList: %s\n", list ); } // end BinarySearchTest constructor ascending order 22 23 24 25 26 Outline { printSearchResults( colors[ 3 ] ); // first item printSearchResults( colors[ 0 ] ); // middle item 27 28 29 printSearchResults( colors[ 7 ] ); // last item printSearchResults( "aqua" ); // below lowest printSearchResults( "gray" ); // does not exist 30 31 printSearchResults( "teal" ); // does not exist } // end method search 32 33 34 // perform searches and display search result private void printSearchResults( String key ) 35 { 36 37 38 39 40 41 42 43 44 45 46 126 // search list for various values private void search() int result = 0; Use method binarySearch of class Collections to search list for specified key System.out.printf( "\nSearching for: %s\n", key ); result = Collections.binarySearch( list, key ); if ( result >= 0 ) System.out.printf( "Found at index %d\n", result ); else System.out.printf( "Not Found (%d)\n",result ); } // end method printSearchResults 47 48 49 Outline public static void main( String args[] ) { BinarySearchTest binarySearchTest = new BinarySearchTest(); 50 binarySearchTest.search(); 51 } // end main 52 } // end class BinarySearchTest Sorted ArrayList: [black, blue, pink, purple, red, tan, white, yellow] Searching for: black Found at index 0 Searching for: red Found at index 4 Searching for: pink Found at index 2 Searching for: aqua Not Found (-1) Searching for: gray Not Found (-3) Searching for: teal Not Found (-7) 127 Algorithms addAll, frequency and disjoint addAll Insert all elements of an array into a collection frequency Calculate the number of times a specific element appear in the collection Disjoint Determine whether two collections have elements in common 128 1 2 3 4 5 6 7 8 9 Outline import java.util.Vector; import java.util.Arrays; import java.util.Collections; public class Algorithms2 { 10 11 12 13 private String[] colors = { "red", "white", "yellow", "blue" }; private List< String > list; private Vector< String > vector = new Vector< String >(); 14 15 16 // create List and Vector // and manipulate them with methods from Collections public Algorithms2() 17 18 19 20 21 22 { 23 24 25 129 // Fig. 19.15: Algorithms2.java // Using algorithms addAll, frequency and disjoint. import java.util.List; // initialize list and vector list = Arrays.asList( colors ); vector.add( "black" ); vector.add( "red" ); vector.add( "green" ); System.out.println( "Before addAll, vector contains: " ); 26 27 28 29 30 31 32 33 Outline // display elements in vector for ( String s : vector ) System.out.printf( "%s ", s ); // add elements in colors to list Collections.addAll( vector, colors ); Invoke method addAll to add elements in array colors to vector System.out.println( "\n\nAfter addAll, vector contains: " ); 34 35 36 // display elements in vector for ( String s : vector ) System.out.printf( "%s ", s ); 37 38 39 // get frequency of "red" 40 int frequency = Collections.frequency( vector, "red" ); 41 42 43 System.out.printf( "\n\nFrequency of red in vector: %d\n", frequency ); 130 Get the frequency of String “red” in Collection vector using method frequency 44 45 46 Outline // check whether list and vector have elements in common boolean disjoint = Collections.disjoint( list, vector ); 47 48 49 50 System.out.printf( "\nlist and vector %s elements in common\n", Invoke method disjoint to test ( disjoint ? "do not have" : "have" ) ); whether Collections list and } // end Algorithms2 constructor vector have elements in common 51 52 public static void main( String args[] ) { 53 54 new Algorithms2(); } // end main 55 } // end class Algorithms2 Before addAll, vector contains: black red green After addAll, vector contains: black red green red white yellow blue Frequency of red in vector: 2 list and vector have elements in common 131 Synchronized Collections Built-in collections are unsynchronized Concurrent access to a Collection can cause errors Java provides synchronization wrappers to avoid this Via set of public static methods public static method headers < T > Collection< T > synchronizedCollection( Collection< T > c ) < T > List< T > synchronizedList( List< T > aList ) < T > Set< T > synchronizedSet( Set< T > s ) < T > SortedSet< T > synchronizedSortedSet( SortedSet< T > s ) < K, V > Map< K, V > synchronizedMap( Map< K, V > m ) < K, V > SortedMap< K, V > synchronizedSortedMap( SortedMap< K, V > m ) 132 Unmodifiable Collections Unmodifiable wrapper Converting collections to unmodifiable collections Throw UnsorrtedOperationException if attempts are made to modify the collection public static method headers < T > Collection< T > unmodifiableCollection( Collection< T > c ) < T > List< T > unmodifiableList( List< T > aList ) < T > Set< T > unmodifiableSet( Set< T > s ) < T > SortedSet< T > unmodifiableSortedSet( SortedSet< T > s ) < K, V > Map< K, V > unmodifiableMap( Map< K, V > m ) < K, V > SortedMap< K, V > unmodifiableSortedMap( SortedMap< K, V > m ) 133