Instantiating an Object of ArrayList
Listing 1 illustrates an object called rowList, which is an array of arrays. As you can see, the data type is Object[]. This data type allows for a flexible approach.
Listing 1 Instantiating an Object of ArrayList
ArrayList<Object[]> rowList = new ArrayList<Object[]>();
In Listing 1, my ArrayList object has been instantiated by calling the default constructor. In other words, I haven't passed a length into the constructor. This results in the creation of an ArrayList object with ten entries. So, it's enough to just get you started! Depending on your needs, you might prefer to allocate an application-specific number at this point. Or you can go with the default value and then add entries while relying on the object to automatically resize itself. It's a nice flexible solution. Later on, I'll describe some of the tradeoffs that represent the price of this flexibility.
How do you now add an entry to the ten-entry rowList object? It's easy enough, as illustrated in Listing 2.
Listing 2 Populating an ArrayList Object
Object[] databaseRow = new Object[dataItemsList.length]; for (loop = 0; loop < dataItemsList.length; loop++) databaseRow[loop] = (Object)(dataItemsList[loop]); rowList.add(databaseRow);
In Listing 2, I instantiate an array of type Object called databaseRow. Remember, this is the base type of my rowList object. I can use a databaseRow object to store a single row of data coming from a database. Because the number of elements in a databaseRow object is fixed at the value of the length of an array dataItemsList.length, I can't read in more than this. But, it's normal that you'll know how many columns are in a database table. This data is defined in the database schema. The harder thing to know is how many rows there are in a given table. As you'll see later, it's this problem that the ArrayList object helps us to solve.
Going back to Listing 2, I populate the elements of the array databaseRow with values taken from an array called dataItemsList. The latter item is my notional database and is derived from an enumerated type called DataItems:
enum DataItems {SOME_DATA, MORE_DATA, EVEN_MORE_DATA};
The enum type DataItems is used to create a corresponding array with the line:
DataItems[] dataItemsList = DataItems.values();
So, this is how I define the number of columns in the databaseRow object. As you can see at the bottom of Listing 2, I just loop through dataItemsList and copy its elements into the array databaseRow. Then, at the end of Listing 2, I add the databaseRow object into the rowList object with the line:
rowList.add(databaseRow);
At this point, we have one row stored in the rowList object. Now clearly, if we were reading from a real database (such as Derby), we would read many rows into the rowList object. As the principle of induction tells us, if it works for one element, it should work for n objects!
We now have a row of data in the rowList object. Let's imagine that you now want to hold onto the data in the rowList object—i.e., you won't be adding any more data to it. You can strip off any unused space in rowList with the following method call:
rowList.trimToSize();
This method reduces the capacity of the rowList object. Remember, we used the default constructor allocation size of 10, so the call to rowList.trimToSize() should result in saving some space. So, we've now populated the rowList ArrayList object and trimmed it down to the required size. Now, how do you examine the data contained in the rowList object? Listing 3 illustrates the slightly odd syntax required for extracting data from an ArrayList object.
Listing 3 Examining the Contents of an ArrayList Object
for (Object[] element : rowList) { copyRow = element; System.out.println("Row has value " + copyRow[0].toString()); }
In Listing 3, I use a for-each loop to copy the data in each element of the rowList object. Figure 1 illustrates the execution of the overall code.
Figure 1 Running the program.
Listing 4 illustrates the complete code that produces the output in Figure 1.
Listing 4 The Complete Example of ArrayList Use
public class ArrayListTest { enum DataItems {SOME_DATA, MORE_DATA, EVEN_MORE_DATA}; public static void main(String[] args) { ArrayListTest arrayListTest = new ArrayListTest(); arrayListTest.manipulateArrayList(); } public void manipulateArrayList() { DataItems[] dataItemsList = DataItems.values(); for (int i = DataItems.SOME_DATA.ordinal(); i <= DataItems.EVEN_MORE_DATA.ordinal(); i++) { System.out.println("Data array " + dataItemsList[i]); } Object[] copyRow = new Object[dataItemsList.length]; ArrayList<Object[]> rowList = new ArrayList<Object[]>(); int loop = 0; Object[] databaseRow = new Object[dataItemsList.length]; for (loop = 0; loop < dataItemsList.length; loop++) databaseRow[loop] = (Object)(dataItemsList[loop]); rowList.add(databaseRow); rowList.trimToSize(); for (Object[] element : rowList) { copyRow = element; System.out.println("Row has value " + copyRow[0].toString()); } }
At the end of Listing 4 is a for-each loop. This serves exactly the same purpose as an iterator in that it allows you to loop through the elements in the collection (i.e., our rowList object). If this is a little easier than using an iterator, then I think it's the way to go. However, for the purposes of comparison, Listing 5 illustrates the use of an iterator in conjunction with an ArrayList object.
Iterator<Object[]> i = rowList.iterator(); while (i.hasNext()) { Object[] databaseRow1 = (Object[])i.next(); for (loop = 0; loop < dataItemsList.length; loop++) System.out.println(databaseRow1[loop]); }
Listing 5 Using an Iterator with an ArrayList Object
The first line in Listing 5 creates an association between an iterator object and the rowList object. Because we know that the rowList object is an instantiation of one of the collection classes, we therefore are guaranteed that the rowList object has an iterator() method. This method returns an object of type Iterator<Object[]>. Using the latter object (called i in this case), you can then loop through the elements via the method i.hasNext(). Each entity the iterator returns via a call to i.next() can be cast to the required type—in our example, an object of type Object[]. Once the cast has occurred, we can then loop through the elements of the array, producing the same data we saw in Figure 1.