java programming: from the ground up chapter 17 the java collections framework

Post on 21-Jan-2016

234 Views

Category:

Documents

1 Downloads

Preview:

Click to see full reader

TRANSCRIPT

Java Programming:From the Ground Up

Chapter 17The Java Collections Framework

Java Collections Framework

The Java Collections Framework is a hierarchy of interfaces and classes used for storing and manipulating groups of objects as a single unit, a collection.

Each collection comes with a set of methods for managing the collection The Java Collections Framework is contained in the java.util package. The ArrayList<E> class is a member

of the Java Collections Framework.

The Collection Hierarchy

The collection hierarchy consists entirely of interfaces except at the lowest levels where concrete classes reside.

The Collection Hierarchy

A partial view of the Collection hierarchy

The Collection Hierarchy

List<E> is an interface that extends Collection<E>.

ArrayList<E> and LinkedList<E> are classes that implementList<E>.

An object belonging to ArrayList<E> or LinkedList<E> is a

collection that can contain duplicate items.

The Collection Hierarchy

Set<E> is an interface that extends Collection<E>.

HashSet<E> and TreeSet<E> implement Set<E>.

An object belonging to HashSet<E> or TreeSet<E> is a collection that is not indexed and does not contain duplicate items.

The Collection<E> interface

Assume that x is an object of a class that implements Collection<E>.

• boolean add(E item)x.add(item) adds item to x and returns true, if the contents of x has been changed. If x belongs to a class that implements Set<E> and x contains item then x.add(item) returns false because Sets do not hold duplicate elements.

• boolean addAll(Collection<E> c) x.addAll(c) appends Collection<E> c to Collection<E> x; x.addAll(c) returns true, if x has been altered, i.e., if the call x.addAll(c) adds any additional items to x.

The Collection<E> interface

• void clear() x.clear() removes all elements from x.

• boolean contains (E item) x.contains(item) returns true if there is a member c, of x, such that c.equals(item) is true.

• boolean containsAll(Collection<E> c) x.containsAll(c) returns true if every element in c is also in x, i.e., if c is a subset of x.

• boolean equals (E item)x.equals(item) returns true if item is equal to x.|

• boolean isEmpty()x.isEmpty() returns true if x has no elements

The Collection<E> interface

• boolean removeAll(Collection c)x.removeAll(c) removes all elements from x that are also in Collection c so that x and c have no common elements; returns true, if any element is removed.

• boolean remove(E item)x.remove(item) removes at most one instance of item from x; returns false if nothing is removed from x.

• boolean retainAll(Collection<E> c) x.retainAll(c) retains all elements of x that are also in c, i.e., x.retainsAll(c) is the intersection of x and c., the collection of elements common to x and c; returns true if any

The Collection<E> interface

• int size() x.size() returns the number of elements in x.

• Object[] toArray() x.toArray() returns an array containing the elements in collection x.

The Collection<E> interface

• Iterator iterator()Given a collection x, it is often desirable to “loop through x” or “step through x,” processing each object in x. In pseudo-code:for each object o in x

process o

An iterator is an object capable of looping through, moving through, or stepping through a collection.

The statementIterator<E> iter = x.iterator();

instantiates an Iterator object.

For any Collection x, you can instantiate one or more Iterator

The Collection<E> interface

Think of an Iterator object as containing an, albeit imaginary, pointer or cursor. Initially, when an iterator for a collection is instantiated, this pointer is positioned just before the first element in a collection.

The Collection<E> interface

Once an Iterator is instantiated, the following methods are available:

• E next() returns the next item of the collection and advances the pointer.

• boolean hasNext() returns true if there is a “next element” in the collection.

• void remove()removes the last element returned by a call to next(). This method can be called only once for each call to next(), otherwise this method throws

an IllegalStateException.

The Collection<E> interface

Assume that x is the Collection [“Harpo” “Groucho” “Zeppo” “Chico”].

Print the contents of a collection and remove each element in turn.:

Each call to remove() is preceded by a call to next().

Iterator<String> iter = x.iterator(); // position pointer before "Harpo"

while ( iter.hasNext()){ System.out.println(iter.next()); // print and advance pointer iter.remove(); // remove the last item printed}

The Set<E> Interface

The classes that implement Set<E> do not contain duplicate objects.

Set<E> interface inherits all the methods of Collection<E>. No new methods are added to the Set<E> interface.

The Set<E> Interface

HashSet

HashSet<E> has two constructors: • HashSet<E>(), and• HashSet<E>(Collection<E> c).

The Set<E> Interface

The HashSet<E> methods are those methods of the Collection<E> interface.

Collection<E> provides methods for:

• inserting objects into a HashSet<E>,• removing objects from a HashSet<E>, and• checking whether or not an object is contained in a

HashSet<E>.

The Set<E> InterfaceHashSet

• A HashSet<E> contains no duplicates, no matter how many times an item is added.

• A HashSet<E> has no methods that allow direct retrieval of an object. The only retrieval mechanism is via an iterator, which means stepping through the set.

• The HashSet class does provide a methodboolean contains(E x)for determining whether or not an object is contained in a HashSet<E>.

• A HashSet<E> is not ordered. Objects contained in a HashSet<E> need not implement the Comparable interface.

The Set<E> InterfaceHashSet

HashSet<E> is an appropriate choice when rapid lookup is paramount and ordering is not required, i.e., when your main concern is whether or not some object is in a collection.

The Set<E> InterfaceHashSet

Example

In the city of Springfield, home of the ever-famous Simpson family, whenever a person votes in a city election, his/her name is added to a list of voters. This action is important because several nefarious residents of Springfield, including Mayor Quimby himself, have been known to vote more than once. To curb ballot stuffing, a person’s name is validated (the list is checked) before he/she is allowed to cast a vote. If a person has already voted, he/she is barred from voting a second time.

The Set<E> InterfaceHashSet

Problem Statement:Write an application that adds a name (String) to a list of voters

and also performs rapid lookup when a potential voter arrives

at the polls.

The Set<E> InterfaceHashSet

HashSet<E> is an excellent choice for the voter list. Storing names in an array is problematic because searching for a name necessitates a linear search, which is slow and inefficient for our purposes. A binary search, though faster than linear search, mandates that the array be kept sorted, which would then make insertion slow and inefficient. HashSet<E> with rapid insertion and lookup is ideal for this situation.

The Set<E> InterfaceHashSet

1. import java.util.*;2. public class SpringfieldElection3. {4. protected HashSet<String> voters; 5. public SpringfieldElection ()6. {7. voters = new HashSet<String>();8. }9. public void validate()10. {11. Scanner input = new Scanner(System.in);12. String name;13. System.out.println("Enter XXX to exit the system");14. System.out.print("Name: ");15. name = input.nextLine();

The Set<E> InterfaceHashSet

16. while ( !name.equals("XXX"))17. {18. if ( voters.contains(name)) // has name voted?19. System.out.println(name+" has already voted");20. else21. {22. System.out.println(name+ " may vote");23. voters.add(name);24. }25. System.out.print("Name: ");26. name = input.nextLine();27. } // end while28. } // end validate29. public static void main(String [] args)30. {31. SpringfieldElection votingCheck = new SpringfieldElection ();32. votingCheck.validate();33. }34. }

The Set<E> InterfaceHashSet

OutputEnter XXX to exit the systemName: Simpson, HomerSimpson, Homer may voteName: Simpson, MargeSimpson, Marge may voteName: Simpson, HomerSimpson, Homer has already votedName: KrustyKrusty may voteName: Flanders, NedFlanders, Ned may voteName: KrustyKrusty has already votedName: Simpson, HomerSimpson, Homer has already votedName: XXX

The SortedSet<E> Interface

SortedSet<E> is an interface that extends Set<E>. Unlike a HashSet<E>, the elements of a class that implements SortedSet<E> are ordered.

This means that the objects belonging to any class that implements SortedSet<E> must be comparable, i.e., E must implement the Comparable interface.

The SortedSet<E> Interface

Assume that x is an object of a class that implements SortedSet<E>.

• E first() x.first() returns the first element of x.

• E last() x.last() returns the last element of x.

• SortedSet headSet(E a) x.headSet(a) returns a reference to a SortedSet containing the elements less than a in x.

• SortedSet tailSet(E z) x.tailSet(z) returns a reference to a SortedSet containing the elements greater than or equal to z in x.

• SortedSet subSet(E start, E end)x.subSet( start, end) returns a reference to a SortedSet containing those objects of x ranging from start to, but not including, end.

TreeSet<E>

TreeSet<E> is a concrete class that implements SortedSet<E>

and consequently Collection<E>.

TreeSet<E>

The constructors of TreeSet<E> are:

public TreeSet<E>();public TreeSet<E>(Collection<E> c);public TreeSet<E>(SortedSet<E> s);

TreeSet<E>

The methods are those of the Collection<E> and SortedSet<E> interfaces.

A TreeSet<E> object does not contain duplicate itrems.

TreeSet<E>

If objects must be kept sorted then a TreeSet<E> is an excellent choice. If objects need not be ordered, a

HashSet<E> is usually a better choice.

TreeSet vs. HashSet

Experiment:

A HashSet and a TreeSet each contain 10,000,000 random numbers. A test program required 5,938 milliseconds to complete 1,000,000 lookups. Using TreeSet<E>, the same program took 10,535 milliseconds.

When lookup is vital and no order is required, HashSet<E> is the clearly the winner.

TreeSet<E>

Example

At the end the day, the mayor of Springfield,expects to see an alphabetized list of all of the citizens who have voted. This sorted data must be retrieved just once, but insertion and validation checks are done continuously

during the day.

TreeSet<E>

Problem Statement

Write an application that does both validation checks and produces a sorted list of voters after the polls have closed.

TreeSet<E>

The following application utilizes both HashSet<E> and TreeSet<E>. HashSet<E> is used during voting hours. However, once the polls close each day, a TreeSet<E> collection is built from the HashSet<E> collection so that a sorted list of voters can be quickly obtained – pleasing Mayor Quimby.

The new class MoreVoting extends the SpringfieldElection class of the previous example

TreeSet<E>

1. import java.util.*;2. public class MoreVoting extends SpringfieldElection3. {4. TreeSet<String> tree;5. public MoreVoting()6. {7. super(); // call the constructor of SpringfieldElection8. tree = new TreeSet<String>();9. }

10. public void makeList()11. {12. int count = 0;13. tree.addAll(voters); // make a TreeSet of the HashSet, voters14. System.out.println();15. System.out.println();16. System.out.println("Today's voters were");17. // use an iterator to step through the TreeSet. Values are sorted18. Iterator<String> iterator = tree.iterator();19. while(iterator.hasNext())20. System.out.println((++count) + ". " + iterator.next());21. }

TreeSet<E>

22. public static void main(String [] args)23. {24. MoreVoting example = new MoreVoting();25. example.validate(); // first use the HashSet26. example.makeList(); // use a TreeSet when we need an ordered

list27. }28. }

Lists

The collection hierarchy is divided into sets and lists.

Sets do not contain duplicate elements.

Lists can contain duplicates.

The List<E> Interface

From Sun’s documentation:

The List<E> interface extends the Collection<E> interface defining an ordered collection that permits duplicates. The interface adds position-oriented operations, as well as the

ability to work with just a part of the list.

The List<E> Interface

Assume that x belongs to a class that implements List<E>.

• boolean add(E a)x.append(a) appends element a to the end of the list.

• void add(int index, E a )x.add(index, a) inserts a into the list at position index. Elements are shifted upwards.

• boolean addAll(Collection<E> c)x.addAll(c) appends the elements in c to the end of the list.

• boolean addAll(int index, Collection<E> c)x.addAll(index, c) inserts the elements in c into the list at position index.

The List<E> Interface

• void clear()x.clear() makes the list, x, empty.

• boolean contains(E x)x.contains(a) returns true if element a is a member of x.

• boolean containsAll(Collection<E> c)x.containsAll(c) returns true if the all members of c belong to x..

• E get(int index)x.get(index) returns the element of x at position index.

• int indexOf(E a)x.indexOf(a) returns the index of the first occurrence of a in x; or –1, if a is not found.

• int lastIndexOf(E a)x.lastIndexOf(a) returns the index of the last instance of a in x; or –1, if a is not found.

The List<E> Interface

• boolean remove(E a)x.remove(a) removes the first occurrence of a from x, returns true if successful.

• E remove(int index)x.remove(index) removes and returns the element at position index.

• boolean removeAll(Collection<E> c)x.removeAll(c) removes all elements from x that are contained in Collection c and returns true if x is altered.

• boolean retainAll(Collection<E> c) x.retainAll(c) retains those elements in c and returns true if x is altered.

• E set(int index, E a ) x.set(index, a) replaces the current element, b, at position index with a and returns b.

The List<E> Interface

• int size()x.size() returns the number of items in x.

• List subList (int start, int end)x.subList(start, end) returns a reference to a List consisting of the elements from position start to position (end – 1).

The List<E> Interface

• ListIterator<E> listIterator() x.listIterator() returns a reference to a ListIterator, which like an Iterator, is used to step through x.

• ListIterator<E> listIterator(int index)x.listIterator(index) returns a reference to a ListIterator that begins at position index.

The ListIterator<E> Interface

ListIterator<E> is an interface that extends Iterator<E>. A ListIterator<E> can be used to traverse a list forward or in reverse. Because ListIterator<E> extends Iterator<E>, ListIterator<E> has methods next(), hasNext(), and remove() of Iterator<E>. The cursor is positioned “between” the next

and previous elements.

The ListIterator<E> Interface

The methods of a ListIterator<E> also include additional methods.

Assume that the object, iter, belongs to a class that implements ListIterator<E>.

• E previous()iter.previous() returns the previous element in the list. This method can be used to traverse the list in reverse. A call to previous() moves the iterator back one element and returns that element.

• boolean hasPrevious()iter.hasPrevious() returns true if a listIterator has another element when proceeding in reverse.

• int nextIndex()iter.nextIndex() returns the index of the element that would be returned by the next call to next() and returns the size of the list if the iterator is positioned at the end of the list.

The ListIterator<E> Interface

• int previousIndex()iter.previousIndex() returns the index of the element that would be returned by the next call to previous() and returns -1 if the iterator is at the beginning of the list.

• void set(E a)iter.set(a) replaces the last element returned by next() or previous() with a.

• void add(E a)iter.add(a) inserts a into the list before the element that would be returned by the next call to next(). In other words, if an iterator is positioned before an object o, a call to add(...) places the new element before o. A call to previous(), after an add operation, returns the newly inserted element.

The ListIterator<E> Interface

The cursor or list pointer of ListIterator<E> is always positioned between the items returned by the next call to previous() or the next call to next()

The ListIterator<E> Interface

ArrayList<E>(See Chapter 16)

• ArrayList<E> is a concrete Java class that implements List<E>.

• An ArrayList<E> object resizes itself, if necessary.

• As with an array, insertion and deletion into the middle of an ArrayList<E> is relatively inefficient because items are shifted with each insertion or deletion.

• ArrayList<E> is a good choice in situations when random access is required and/or insertion and deletion usually occur at the end of the list.

• Like an array, the elements of an ArrayList<E> are indexed from 0

The LinkedList<E> Class

The LinkedList<E> class, like the ArrayList<E> class, implements the List<E> interface, and consequently the Collection<E> interface

The LinkedList<E> Class

Java’s implementation of LinkedList<E> is a slightly more complicated version of the LList<E> class of the previous chapter. Like the LList<E> class of Chapter 16.

LinkedList<E> is built by linking nodes together; but unlike LList<E>, each node contains two references – one pointing to the next node on the list and the other pointing to the previous node. Such a list is sometimes called a doubly

linked list.

The LinkedList<E> Class

A doubly linked list. Each node has two reference fields

The LinkedList<E> Class

Although the methods of LinkedList<E> and ArrayList<E> are functionally similar, there are some notable differences between the classes regarding implementation:

• Insertion into an ArrayList<E> at position i, requires that all references in positions greater or equal to i be shifted upwards one location. In contrast, insertion into the middle of a LinkedList<E> requires that a new node be allocated and at most

four references adjusted. No elements are relocated.

• Access to any element in an ArrayList<E> is immediate, i.e., an ArrayList<E> (like an array) provides direct access to any element. On the other hand, accessing the nth node in a LinkedList<E> involves

traversing the list.

The LinkedList<E> Class

The LinkedList<E> class has the following constructors:

• LinkedList<E> ();• LinkedList<E> (Collection<E> c);

There is no constructor that sets the initial size of the list. A list is initially empty and grows and shrinks as single items are added or deleted.

The LinkedList<E> Class

In addition to the methods of the List interface, LinkedList<E implements the following methods that are not available to ArrayList<E> objects:

• void addFirst(E x)

• void addLast(E x)

• E getFirst()

• E getLast()

• E removeFirst()

• E removeLast()

ArrayList or LinkedList

Both classes share the same interface.

Both classes implement (mostly) the same methods.

Are they interchangeable? Not usually

ArrayList or LinkedList

ArrayList<E> provides direct access to an element. Access to a specific element of a LinkedList<E> requires traversing the list.

On the other hand, insertion and removal from an ArrayList may require shifting many data. This is not the case with LinkedList.

The choice depends on the application.

The for-each loop

The for-each loop is a convenience that can be used to iterate through a collection without having to explicitly instantiate an iterator.

The for-each loop

Assume that names is a collection of strings.

The collection can be displayed using the following for-each construction:

for ( String name : names) // read: ” for each” String, name, in the collection names

System.out.println(name);

The for-each loop

• The for-each loop cannot be used to alter a collection.

The following fragment is illegal.

for (String name : names)

names.remove(); // ILLEGAL

• Methods such as add(), remove(), and clear() cannot be used in conjunction with the for-each construction

The for-each loop

The following iteration sums a list of integers and does not alter a collection.

int sum = 0; for ( Integer number : list) // for each Integer, number, in the collection list sum = sum+ number; // This is legal

The for-each loop

The equivalent code, using an iterator, is:

int sum = 0;Iterator<Integer> iter = list.iterator();while( iter.hasNext()

sum = sum + iter.next

top related