- Information
- AI Chat
The Collections and Framework Module 2
Advanced JAVA AND J2EE (18cs644)
Visvesvaraya Technological University
Preview text
The Collections and Framework
Collections Overview
The Java Collections Framework standardizes the way in which groups of objects are handled by your programs. Prior to the Collections Framework, Java provided ad hoc classes such as Dictionary , Vector , Stack , and Properties to store and manipulates groups of objects.
Collections are an answer to these (and other) problems. First, the framework had to be high-performance. The implementations for the fundamental collections (dynamic arrays, linked lists, trees, and hash tables) are highly efficient.
Second, the framework had to allow different types of collections to work in a similar manner and with a high degree of interoperability.
Third, extending and/or adapting a collection had to be easy. Toward this end, the entire Collections Framework is built upon a set of standard interfaces. Several standard implementations (such as Linked List , Hash Set , and Tree Set ) of these interfaces are provided that you may use as-is.
Finally, mechanisms were added that allow the integration of standard arrays into the Collections Framework.
Algorithms are another important part of the collection mechanism.
Another item closely associated with the Collections Framework is the Iterator interface. An iterator offers a general-purpose, standardized way of accessing the elements within a Collection, one at a time. Thus, an iterator provides a means of enumerating the contents of a collection. Because each collection implements Iterator , the elements of any collection class can be accessed through the methods defined by Iterator.
In addition to collections, the framework defines several map interfaces and classes. The collection mechanism was retrofitted to some of the original classes defined by java so that they too could be integrated into the new system.
Recent Changes to Collections
The changes were caused by the addition of generics, autoboxing/unboxing, and the for-each style for loop, by JDK 5.
(i) Generics Fundamentally Change the Collections Framework The addition of generics caused a significant change to the Collections Framework because the entire Collections Framework has been reengineered for it. All collections are now generic, and many of the methods that operate on collections take generic type parameters.
Generics add the one feature that collections had been missing: type safety. Prior to generics, all collections stored Object references, which meant that any collection could store any type of object. Thus, it was possible to accidentally store incompatible types in a collection. Doing so could result in run-time type mismatch errors. With generics, it is possible to explicitly state the type of data being stored, and run-time type mismatch errors can be avoided.
(ii) Autoboxing Facilitates the Use of Primitive Types Autoboxing/unboxing facilitates the storing of primitive types in collections. A collection can store only references, not primitive values. In the past, if you wanted to store a primitive value, such as an int , in a collection, you had to manually box it into its type wrapper. When the value was retrieved, it needed to be manually unboxed (by using an explicit cast) into its proper primitive type.
(iii) The For-Each Style for Loop All collection classes in the Collections Framework have been retrofitted to implement the Iterable interface, which means that a collection can be cycled through by use of the for-each style for loop. In the past, cycling through a collection required the use of an iterator, with the programmer manually constructing the loop. Although iterators are still needed for some uses, in many cases, iterator-based loops can be replaced by for loops.
A Class Cast Exception is generated when one object is incompatible with another, such as when an attempt is made to add an incompatible object to a collection. A Null Pointer Exception is thrown if an attempt is made to store a null object and null elements are not allowed in the collection. An Illegal Argument Exception is thrown if an invalid argument is used. An Illegal State Exception is thrown if an attempt is made to add an element to a fixed-length collection that is full.
Objects are added to a collection by calling add( ). Notice that add( ) takes an argument of type E , You can add the entire contents of one collection to another by calling addAll( ).
You can remove an object by using remove( ). To remove a group of objects, call removeAll( ). You can remove all elements except those of a specified group by calling retainAll( ).
To empty a collection, call clear( ).
You can determine whether a collection contains a specific object by calling contains( ).
To determine whether one collection contains all the members of another, call containsAll( ).
You can determine when a collection is empty by calling isEmpty( ). The number of elements currently held in a collection can be determined by calling size( ). The toArray( ) methods return an array that contains the elements stored in the invoking collection. The first returns an array of Object. Two collections can be compared for equality by calling equals( ). For example, you can implement equals( ) so that it compares the values of elements stored in the collection. Alternatively, equals( ) can compare references to those elements. One more very important method is iterator( ) , which returns an iterator to a collection.
(i) The List Interface The List interface extends Collection and declares the behavior of a collection that stores a sequence of elements.
Elements can be inserted or accessed by their position in the list, using a zero-based index. A list may contain duplicate elements. List is a generic interface that has this declaration: interface List<E> Here, E specifies the type of objects that the list will hold.
In addition to the methods defined by Collection , List defines some of its own, which are summarized in Table.
can obtain a sublist of a list by calling subList( ) , specifying the beginning and ending indexes of the sublist. As you can imagine, subList( ) makes list processing quite convenient.
(ii) The Set Interface The Set interface defines a set. It extends Collection and declares the behavior of a collection that does not allow duplicate elements. Therefore, the add( ) method returns false if an attempt is made to add duplicate elements to a set. Set is a generic interface that has this declaration: interface Set<E> Here, E specifies the type of objects that the set will hold.
(iii) The SortedSet Interface The SortedSet interface extends Set and declares the behavior of a set sorted in ascending order. SortedSet is a generic interface that has this declaration: interface SortedSet<E> Here, E specifies the type of objects that the set will hold.
In addition to those methods defined by Set , the SortedSet interface declares the methods summarized in Table. Several methods throw a No Such Element Exception when no items are contained in the invoking set.
A Class Cast Exception is thrown when an object is incompatible with the elements in a set. A Null Pointer Exception is thrown if an attempt is made to use a null object and null is not allowed in the set. SortedSet defines several methods that make set processing more convenient. To obtain the first object in the set, call first( ). To get the last element, use last( ). You can obtain a subset of a sorted set by calling subSet( ) , specifying the first and last object in the set. If you need the subset that starts with the first element in the set, use headSet( ). If you want the subset that ends the set, use tailSet( ).
An Illegal Argument Exception is thrown if an invalid argument is used.
(iv) The NavigableSet Interface
It extends SortedSet and declares the behavior of a collection that supports the retrieval of elements based on the closest match to a given value or values. NavigableSet is a generic interface that has this declaration:
interface NavigableSet<E>
Here, E specifies the type of objects that the set will hold. In addition to the methods that it inherits from SortedSet , NavigableSet adds those summarized in Table. A Class Cast Exception is thrown when an object is incompatible with the elements in the set. A Null Pointer Exception is thrown if an attempt is made to use a null object and null is not allowed in the set. An Illegal Argument Exception is thrown if an invalid argument is used.
Several methods throw a ClassCastException when an object is incompatible with the elements in the queue. A NullPointerException is thrown if an attempt is made to store a null object and null elements are not allowed in the queue. An IllegalArgumentException is thrown if an invalid argument is used. An IllegalStateException is thrown if an attempt is made to add an element to a fixed-length queue that is full. A NoSuchElementException is thrown if an attempt is made to remove an element from an empty queue.
There are two methods that obtain and remove elements: poll( ) and remove( ). The difference between them is that poll( ) returns null if the queue is empty, but remove( ) throws an exception. There are another two methods, element( ) and peek( ) , that obtain but don’t remove the element at the head of the queue. They differ only in that element( ) throws an exception if the queue is empty, but peek( ) returns null. Finally, notice that offer( ) only attempts to add an element to a queue. Because some queues have a fixed length and might be full, offer( ) can fail.
(vi) The Deque Interface It extends Queue and declares the behavior of a double-ended queue. Double-ended queues can function as standard, first-in, first-out queues or as last-in, first-out stacks. Deque is a generic interface that has this declaration: interface Deque<E> Here, E specifies the type of objects that the deque will hold. In addition to the methods that
it inherits from Queue , Deque adds those methods summarized in Table. Several methods throw a Class Cast Exception when an object is incompatible with the elements in the deque.
The following sections examine the concrete collection classes and illustrate their use. (i) The ArrayList Class The ArrayList class extends AbstractList and implements the List interface. ArrayList is a generic class that has this declaration: class ArrayList<E> Here, E specifies the type of objects that the list will hold. ArrayList supports dynamic arrays that can grow as needed. An ArrayList is a variable-length array of object references. That is, an ArrayList can dynamically increase or decrease in size. Array lists are created with an initial size. When this size is exceeded, the collection is automatically enlarged. When objects are removed, the array can be shrunk. ArrayList has the constructors shown here: ArrayList( ) ArrayList(Collection<? extends E> c ) ArrayList(int capacity) The first constructor builds an empty array list. The second constructor builds an array list that is initialized with the elements of the collection c. The third constructor builds an array list that has the specified initial capacity. The capacity is the size of the underlying array that is used to store the elements. The capacity grows automatically as elements are added to an array list.
The following program shows a simple use of ArrayList. An array list is created for objects of type String , and then several strings are added to it. (Recall that a quoted string is translated into a String object.) The list is then displayed. Some of the elements are removed and the list is displayed again. // Demonstrate ArrayList. import java.*; class ArrayListDemo { public static void main(String args[]) { // Create an array list. ArrayList<String> al = new ArrayList<String>(); System("Initial size of al: " + al()); // Add elements to the array list. al("C"); al("A"); al("E"); al("B"); al("D"); al("F"); al(1, "A2"); System("Size of al after additions: " + al()); // Display the array list. System("Contents of al: " + al); // Remove elements from the array list. al("F"); al(2); System("Size of al after deletions: " + al()); System("Contents of al: " + al); } } The output from this program is shown here: Initial size of al: 0 Size of al after additions: 7 Contents of al: [C, A2, A, E, B, D, F] Size of al after deletions: 5
type of array. The following program demonstrates its use: // Convert an ArrayList into an array. import java.*; class ArrayListToArray { public static void main(String args[]) { // Create an array list. ArrayList<Integer> al = new ArrayList<Integer>(); // Add elements to the array list. al(1); al(2); al(3); al(4); System("Contents of al: " + al); // Get the array. Integer ia[] = new Integer[al()]; ia = al(ia); int sum = 0; // Sum the array. for(int i : ia) sum += i; System("Sum is: " + sum); } } The output from the program is shown here: Contents of al: [1, 2, 3, 4] Sum is: 10 The program begins by creating a collection of integers. Next, toArray( ) is called and it obtains an array of Integer s. Then, the contents of that array are summed by use of a for-each style for loop. Autoboxing makes it possible to pass values of type int to add( ) without having to manually wrap them within an Integer , as the program shows. Autoboxing causes them to be automatically wrapped. (ii) The LinkedList Class The LinkedList class extends Abstract Sequential List and implements the List , Deque , and Queue interfaces. It provides a linked-list data structure.
LinkedList is a generic class that has this declaration: class LinkedList<E> Here, E specifies the type of objects that the list will hold. LinkedList has the two constructors shown here: LinkedList( ) LinkedList(Collection<? extends E> c ) The first constructor builds an empty linked list. The second constructor builds a linked list that is initialized with the elements of the collection c. Because LinkedList implements the Deque interface, you have access to the methods defined by Deque.
For example, to add elements to the start of a list you can use addFirst( ) or offerFirst( ). To add elements to the end of the list, use addLast( ) or offerLast( ). To obtain the first element, you can use getFirst( ) or peekFirst( ). To obtain the last element, use getLast( ) or peekLast( ). To remove the first element, use removeFirst( ) or pollFirst( ).
To remove the last element, use removeLast( ) or pollLast( ). The following program illustrates LinkedList : // Demonstrate LinkedList. import java.*; class LinkedListDemo { public static void main(String args[]) { // Create a linked list. LinkedList<String> ll = new LinkedList<String>(); // Add elements to the linked list. ll("F"); ll("B"); ll("D"); ll("E"); ll("C"); ll("Z"); ll("A"); ll(1, "A2");
The following constructors are defined: HashSet( ) HashSet(Collection<? extends E> c) HashSet(int capacity) HashSet(int capacity, float fillRatio) The first form constructs a default hash set. The second form initializes the hash set by using the elements of c. The third form initializes the capacity of the hash set to capacity. (The default capacity is 16.) The fourth form initializes both the capacity and the fill ratio (also called load capacity) of the hash set from its arguments. The fill ratio must be between 0. and 1, and it determines how full the hash set can be before it is resized upward. Specifically, when the number of elements is greater than the capacity of the hash set multiplied by its fill ratio, the hash set is expanded. 0 is used. HashSet does not define any additional methods beyond those provided by its super classes and interfaces. It is important to note that HashSet does not guarantee the order of its elements, because the process of hashing doesn’t usually lend itself to the creation of sorted sets. If you need sorted storage, then another collection, such as TreeSet , is a better choice. Here is an example that demonstrates HashSet : // Demonstrate HashSet. import java.*; class HashSetDemo { public static void main(String args[]) { // Create a hash set. HashSet<String> hs = new HashSet<String>(); // Add elements to the hash set. hs("B"); hs("A"); hs("D"); hs("E"); hs("C"); hs("F"); System(hs); } }
The following is the output from this program: [D, A, F, C, B, E] As explained, the elements are not stored in sorted order, and the precise output may vary.
(iv) The LinkedHashSet Class The LinkedHashSet class extends HashSet and adds no members of its own. It is a generic class that has this declaration: class LinkedHashSet<E> Here, E specifies the type of objects that the set will hold. Its constructors parallel those in HashSet. LinkedHashSet maintains a linked list of the entries in the set, in the order in which they were inserted. This allows insertion-order iteration over the set. That is, when cycling through a LinkedHashSet using an iterator, the elements will be returned in the order in which they were inserted. This is also the order in which they are contained in the string returned by toString( ) when called on a LinkedHashSet object. To see the effect of LinkedHashSet , try substituting LinkedHashSet for HashSet in the preceding program. The output will be [B, A, D, E, C, F] which is the order in which the elements were inserted.
(v) The TreeSet Class TreeSet extends AbstractSet and implements the NavigableSet interface. It creates a collection that uses a tree for storage. Objects are stored in sorted, ascending order. Access and retrieval times are quite fast, which makes TreeSet an excellent choice when storing large amounts of sorted information that must be found quickly. TreeSet is a generic class that has this declaration: class TreeSet<E> Here, E specifies the type of objects that the set will hold. TreeSet has the following constructors: TreeSet( ) TreeSet(Collection<? extends E> c) TreeSet(Comparator<? super E> comp) TreeSet(SortedSet<E> ss)
The Collections and Framework Module 2
Course: Advanced JAVA AND J2EE (18cs644)
University: Visvesvaraya Technological University
- Discover more from: