Using Arrays and Collections in Java SE 7
Before allocation of new array
After allocation of new array
Usingcommand-linearguments
Chapter 4
When a Java application executes, the first method that is executed is the main method. This method passes an argument, an array of String objects called args. These strings correspond to those provided on the command line.
The length property of a Java array will tell us how many command-line arguments were used. The first argument of the array will contain the first command-line parameter. The second will contain the secondcommand-line parameter, and so forth.
The following CommandLineDemo application illustrates the use of the args array:
[java]
public class CommandLineDemo {
public static void main(String args[]) { System.out.println(“The command line has ” +
args.length + ” arguments”);
for (int i = 0; i < args.length; i++) { System.out.println("tArgument Number " + i + ": " + args[i]); } } } [/java] Consider that the application is invoked with the following command-line arguments: java CommandLineDemo /D 1024 /f test.dat
The output of the program would appear as follows:
The command line has 4 arguments Argument Number 0: /D Argument Number 1: 1024
Argument Number 2: /f
Argument Number 3: test.dat
The Arrays class
The java.util.Arrays class possesses several methods useful for working with arrays. Every method of the class is a static method which means that we do not have to create an instance of the Arrays class before weuse its methods. The class is designed to work with arrays and perform common operations on arrays. The types of operations available include:
• Returning a List based on an array
• Performing a binary search
• Making copies of an array
• Determining the equality of two arrays
• Filling arrays
• Sorting arrays
We have seen the use of several of these techniques in earlier sections. Here we will demonstrate the use of the asList, fill, toString, and deepToString methods.
Consider the following declarations. We will declare an integer array and then an array list. Two strings will be added to the ArrayList object. We will also create an array of mixed objects and an array of strings. TheArrayList class is discussed in more detail in the ArrayList section:
[java]
int arr1[] = new int[5];
ArrayList list = new ArrayList();
list.add(“item 1”);
list.add(“item 2”);
Object arr2[] = {“item 3”, new Integer(5), list}; String arr3[] = {“Pine”, “Oak”, “Maple”, “Walnut”};
[/java]
Next, we will fill the integer array with the number 5 using the fill method:
[java]
Arrays.fill(arr1,5);
[/java]
The asList, toString, and deepToString methods are then used against these arrays, shown as follows:
System.out.println(Arrays.asList(arr3)); System.out.println(Arrays.toString(arr1)); System.out.println(Arrays.deepToString(arr2));
Chapter 4
When executed we get the following output:
[Pine, Oak, Maple, Walnut] [5, 5, 5, 5, 5]
[item 3, 5, [item 1, item 2]]
The asList method takes its array argument and returns a java.util.List object representing the array. If either the array or the list is modified, their corresponding elements are modified. This is demonstrated in the following example:
List list2 = Arrays.asList(arr3); list2.set(0, “Birch”); System.out.println(Arrays.toString(arr3));
The output of this sequence follows:
[Birch, Oak, Maple, Walnut]
The toString method returns a string representation of the array. The deepToString method is intended to return a string representation of its array argument where the array is more complex. This was reflectedin arr2 which contains different objects including a list.
Key points to remember when using arrays
When working with arrays remember:
• Array indexes start at 0
• Indexes have to be integers
• An array can hold primitive data types or objects
• Arrays provide constant time random access which is an efficient way of accessing data
• Arrays provide good locality of reference
• Arrays are more difficult to insert or remove elements than other data structures
• An index to an invalid element is possible
Locality of reference refers to the idea that if one data item is accessed, it is likely that another nearby data item will also be accessed. This results in faster read and write operations and is an important concept in virtual operating systems. Accessing elements of an array can be faster than accessing elements of a linked list when the linked list is spread across the memory.
Be careful when accessing elements of an array. If the array is not properly initialized, then the element being indexed may be invalid resulting in a run-time or logic error.
Collections
The Collections Framework was introduced in Java 2 as a set of interfaces and classes that are superior to many of the interfaces and classes found in the earlier java.util package such as Vector, Stack, and HashTable. These interfaces and classes should always be used instead of the older ones whenever possible. Many of the Collection Framework interfaces and classes are summarized in the following table:
Interface Class
Set HashSet
TreeSet
List ArrayList
LinkedList
Map HashMap
TreeMap
The Collection Framework is covered in more detail at http://java.sun.com/ developer/onlineTraining/collections/Collection.html. Here, we will address the ArrayList class as it is a certification topic. It isrecommended that the ArrayList class be used when a List is needed. As we will see, iterators are used with the ArrayList to support traversal of the list. We will start our discussion with coverage of this topic.
Iterators
Iterators provide a means of traversing a set of data. It can be used with arrays and various classes in the Collection Framework. The Iterator interface supports the following methods:
•next: This method returns the next element
•hasNext: This method returns true if there are additional elements
•remove: This method removes the element from the list
Chapter 4
The remove method is an optional Iterator method. If an attempt is made to use this method and the implementation of the interface does not support this method, then an UnsupportedOperationExceptionexception is thrown.
The ListIterator interface, when available, is an alternative to the Iterator
interface. It uses the same methods and provides additional capabilities including:
• Traversal of the list in either direction
• Modification of its elements
• Access to the element’s position
The methods of the ListIterator interface include the following:
•next: This method returns the next element
•previous: This method returns the previous element
•hasNext: This method returns true if there are additional elements that follow the current one
•hasPrevious: This method returns true if there are additional elements that precede the current one
•nextIndex: This method returns the index of the next element to be returned by the next method
•previousIndex: This method returns the index of the previous element to be returned by the previous method
•add: This method inserts an element into the list (optional)
•remove: This method removes the element from the list (optional)
•set: This method replaces an element in the list (optional)
ArrayList
The ArrayList class has several useful characteristics:
• It is flexible
• Grows as needed
• Possesses many useful methods
• Access is performed in constant time
• Insertion/deletion is performed in linear time
• Can be traversed with indexes, for-each loops, or iterators
ArrayList uses an array internally. When it needs to grow, elements are copied from the old array to the new array.
The ArrayList class is not synchronized. When an iterator is obtained for a ArrayList object, it is susceptible to possible simultaneous overwrites with loss of data if modified in a concurrent fashion. When multiple threads
access the same object, it is possible that they may all write to the object at the same time, that is, concurrently. When this simultaneous overwrite occurs, a ConcurrentModificationException exception isthrown.
Creating ArrayList
The ArrayList class possesses the following three constructors:
• A default constructor
• One that accepts a Collection object
• One that accepts an initial capacity
The capacity of a ArrayList object refers to how many elements the list can hold. When more elements need to be added and the list is full, the size of the list will be automatically increased. The initial capacity of aArrayList created with its default constructor is 10. The following example creates two lists, one with a capacity of 10 and the second with a capacity of 20:
ArrayList list1 = new ArrayList(); ArrayList list2 = new ArrayList(20);
The ArrayList class supports generics. Here, a list of strings is created:
ArrayListlist3 = new ArrayList();
We will use list3 in the examples that follow.
Adding elements
There are several methods available for adding elements to an ArrayList. They can be placed into one of the following two categories:
• Appends one or more elements to the end of the list
• Inserts one or more elements at a position within the list
Chapter 4
The simplest case is illustrated here where a string is added to the end of creatures:
ArrayListcreatures = new ArrayList();
creatures.add(“Mutant”); creatures.add(“Alien”); creatures.add(“Zombie”); System.out.println(creatures);
The output of the print statement follows:
[Mutant, Alien, Zombie]
To insert an element at the index after the first element we use an index of 1:
[java]
creatures.add(1,”Godzilla”); System.out.println(creatures);
[/java]
Executing the code will verify the actions, as shown below:
[Mutant, Godzilla, Alien, Zombie]
The addAll method can also be used with Collections, as illustrated below:
[java]
ArrayList cuddles = new ArrayList();
cuddles.add(“Tribbles”);
cuddles.add(“Ewoks”);
creatures.addAll(2, cuddles); System.out.println(creatures);
[/java]
This will result in the cuddles being placed after the second element in the list, as shown below:
[Mutant, Godzilla, Tribbles, Ewoks, Alien, Zombie]
The addAll method can also be used without an index argument. In this case, the new elements are added to the end of the list.
Retrieving elements
To retrieve an element at a given position, use the get method. This method takes a single integer index value. In the following example, we retrieve the third element of the list. Assuming that the creatures list contains[Mutant, Godzilla, Tribbles, Ewoks, Alien, Zombie], the following statement will retrieve Tribbles:
String element = creatures.get(2);
The index of an element can be obtained using the indexOf method as illustrated in the next code sequence. If the element does not exist, the method will return a -1.
[java]
System.out.println(creatures.indexOf(“Tribbles”)); System.out.println(creatures.indexOf(“King Kong”));
[/java]
Executing this code will generate the following output:
2
-1
The indexOf method will return the index of the first element found. The
lastIndexOf method will return the index of the last element found in the list.
The toArray method will return an array of the objects in the list. In this example, the creatures list is returned and assigned to the complete array. If the array is not large enough, as is the case here, a new array iscreated and returned.
[java]
String[] complete = new String[0]; complete = creatures.toArray(complete); for(String item : complete) {
System.out.print(item + ” “);
} System.out.println();
[/java]
When executed, we get the following output:
Mutant Godzilla Tribbles Ewoks Alien Zombie
There is also a subList method that returns part of the list given the starting and ending indexes.
Traversing a ArrayList object
To traverse a ArrayList object we can use one of several approaches:
• A simple for statement
• A for-each statement
• Using Iterator
• Using ListIterator
Chapter 4
We can use a for loop but it is more prone to error. The following code will display the list from the beginning to the end:
[java]
for(int i = 0; i < creatures.size(); i++) { System.out.print(creatures.get(i) + " ");
} System.out.println();
[/java]
Notice the use of the size method, which returns the number of elements in the list. The for-each statement is the simplest approach, as illustrated in the following code snippet:
[java]
for(String creature : creatures) { System.out.print(creature + " ");
} System.out.println();
[/java]
The iterator method returns a Iterator object, as shown below:
[java]
Iterator iterator = creatures.iterator();
[/java]
while(iterator.hasNext()) { System.out.print(iterator.next() + " ");
} System.out.println();
The ListIterator method returns a ListIterator object:
ListIteratorlistIterator =
creatures.listIterator();
while(listIterator.hasNext()) { System.out.print(listIterator.next() + " ");
} System.out.println();
All four of these techniques will produce the same output as follows:
Mutant Godzilla Tribbles Ewoks Alien Zombie
If we add the following code to the end of the previous code sequence, we can traverse the list in reverse order, as shown in the following code snippet:
[java]
while(listIterator.hasPrevious()) { System.out.print(listIterator.previous() + ” “);
} System.out.println();
[/java]
The output is as follows:
Zombie Alien Ewoks Tribbles Godzilla Mutant
Sorting a ArrayList object
While there are no specific methods in the ArrayList class for sorting, we can use the Arrays class’ sort method, as illustrated in the following code snippet:
Collections.sort(creatures); System.out.println(creatures);
The output is as follows:
[Alien, Ewoks, Godzilla, Mutant, Tribbles, Zombie]
An overloaded version of this method takes a Comparator object. This object determines how comparisons are made.
Other ArrayList methods
We can modify an element of a list using the set method. This method takes an index of the element to replace, and the new value. For example, to replace the first element of the creatures list with the string Ghoul wecan use the following code:
creatures.set(0,”Ghoul”); System.out.println(creatures);
The replacement is verified by the following output:
[Ghoul, Godzilla, Tribbles, Ewoks, Alien, Zombie]
We can remove all or some of the elements of a list. The clear method will remove all elements. The remove method removes a single element and the removeAll method removes all values in a given collection from the list. The following code sequence illustrates these methods. The cuddles ArrayList was defined in the Adding elements section:
[java]
System.out.println(creatures); creatures.remove(0); System.out.println(creatures);
creatures.remove(“Alien”); System.out.println(creatures);
creatures.removeAll(cuddles); System.out.println(creatures);
creatures.clear(); System.out.println(creatures);
[/java]
Chapter 4
The output of this sequence is as follows:
[Mutant, Godzilla, Tribbles, Ewoks, Alien, Zombie] [Godzilla, Tribbles, Ewoks, Alien, Zombie] [Godzilla, Tribbles, Ewoks, Zombie]
[Godzilla, Zombie] []
While ArrayList is a powerful class, arrays should still be used if:
• There is a known number of elements
• It has a small fixed upper bound
• Primitive data types are needed for efficiency
• No elements need to be inserted
Encapsulating collections
When using a collection within a class, hide the collection to prevent inadvertent modification of the collection. For example, if a class encapsulates an ArrayList of Books, then public methods should be provided to permit access to the collection. In the following example, a class called Library hides an ArrayList of Book objects:
[java]
public class Library {
private ArrayList books = new ArrayList();
public Book getBook(int index) {
return books.get(index);
}
public void addBook(Book book) {
books.add(book);
}
public List getBooks() {
return books;
}
}
[/java]
This is a good example of data encapsulation. However, be sure to not inadvertently expose private data. In the getBook method we returned a reference to the book. This reference allows the user to modify the book. Ifthis modification should not
be allowed, then a copy of the book can be returned instead, as shown below. This assumes that the Book class has a constructor that makes a new copy of a book based upon the constructor’s argument:
[java]
public Book getBook (int index) {
return new Book(books.get(index));
}
[/java]
The same problem occurs with the getBooks method. It returns a reference to the private books reference variable of the Library class. This method can be replaced with the following implementation to ensure proper data encapsulation:
[java]
public List getBooks() {
ArrayList list = new ArrayList(books.size());
for(Book book : books) {
list.add(new Book(book));
}
return list;
}
[/java]
Summary
In this chapter we examined the creation and use of arrays and instances of the ArrayList class. We also detailed the use of the Arrays class in support of various array operations.
Arrays contain one or more dimensions and are treated as objects. Care must be taken while using arrays to avoid problems accessing their elements. Problems can be avoided with a good understanding of how arrays are allocated in memory and of how to perform various operations, such as copying and comparing arrays, on them. Arrays are useful when we need a list of a fixed size as it allows efficient access of its elements.
The Arrays class provides a number of static methods that support arrays. For example, we can use the Arrays class to make copies of arrays, sort arrays, and fill arrays.
The ArrayList class provides an alternate approach for dealing with lists of data. It provides numerous methods for manipulating a list and will grow as needed when new elements are added to the list. This is one of its primary advantages over arrays. As with most data structures, it is important to encapsulate information in a class to help reduce the complexity of software development.
Now that we’ve learned about arrays, we’re ready to look more carefully at the various looping constructs available in Java. We will examine these constructs in the next chapter.
The Collections Framework introduced several new interfaces and classes to replace older versions in the java.util package. We examined the ArrayList class and its methods used to manipulate its elements. TheArrayList class is more flexible than an array and is particularly useful for inserting and removing elements.
Certification objectives covered
In this chapter we covered the following certification objectives:
• Using one-dimensional arrays
• Using multidimensional arrays
• Declaring and using ArrayList
Test your knowledge
1. Which of the following statements will compile without an error?
a. int arr[];
b. int arr[5];
c. int arr[5] = {1,2,3,4,5};
d. int arr[] = {1,2,3,4,5};
2. Which of the following declares an array that supports two rows and a variable number of columns?
a. int arr[][] = new int[2][3];
b. int arr[][] = new int[2][]; c. int arr[][] = new int[][]; d. int arr[][] = new int[][3];
3. Given the following code, which of the following statements can be used to determine if cat can be found in the list?
ArrayListlist = new ArrayList<>();
list.add(“dog”); list.add(“cat”); list.add(“frog”);
a. list.contains(“cat”) b. list.hasObject(“cat”) c. list.indexOf(“cat”)
d. list.indexOf(1)
- In-depth understanding of Java through the examination of objects and methods
- Extensive code examples and figures to illustrate key concepts in Java SE 7 including memory usage
- Additional coverage of good programming and design practices as they relate to the certification objectives
- Step-by-step coverage of certification exam topics in a simplified and easy-to-learn manner