Developer

Java tips for list iteration and bean comparisons

Discover the secrets of the ListIterator and BeanComparator utility classes with these nifty Java tips. The former makes examining lists easier, while the latter is a generic comparator that can act upon any Java Bean.


These tips originally appeared in the Builder.com Java e-newsletter.

Iterating over lists and sorting Java Beans becomes much easier with the clever application of utility interfaces. First, discover how to use ListIterator to make examining list contents easier, and then find out how to build a BeanComparator using a Jakarta utility class.

Modify a list while iterating using ListIterator
While the Iterator interface includes the remove method, sometimes you need to do more than just remove elements from a collection. If you happen to have a list, you can use ListIterator. This is an extension of Iterator with extra methods to modify the list during iteration and to aid in the process.

ListIterator adds six methods: Four provide help when iterating, and two allow the list to be modified:
 
boolean hasPrevious();
java.lang.Object previous();
int nextIndex();
int previousIndex();
void set(java.lang.Object);
void add(java.lang.Object);

 

Using these methods, you can walk backwards through a list by creating a ListIterator that starts at the end of the list:
 
ListIterator listItr =
list.listIterator(list.size()-1);
while(listItr.hasPrevious()) {
System.err.println(listItr.previous());
}

 

Or, you can avoid using a counter variable in an iteration by checking hasNext() and modify list contents as I did in the code below:
 
ListIterator listItr = list.listIterator();
while(listItr.hasNext()) {
Object obj = listItr.next();
if(someImaginaryTest(obj)) {
// Replace at the same index.
anotherList.set(listItr.previousIndex(), obj);
}
}

 

Alternatively, you can modify the list you're iterating. One way in which to set all integers in a list to zero would be:
 
ListIterator listItr = list.ListIterator();
Integer zero = new Integer(0);
while(listItr.hasNext()) {
Object obj = listItr.next();
listItr.set(zero);
}

 

Lastly, ListIterator provides an add method. This method adds an object after your current position in the iteration, so you are setting the next object that will be seen. This can help to create on-the-fly processing. For example, to recursively iterate over all the files in a directory, you could use the following code:
 
LinkedList list = new LinkedList(new File("/"));
ListIterator listItr = list.listIterator();
while(listItr.hasNext()) {
File file = (File)listItr.next();
if(file.isDirectory()) {
// add all the files/directories to the list
File[] contents = file.listFiles();
for(int i=0; i<contents.length; i++) {
listItr.add(contents[i]);
}
} else {
// do something to the File
}
}

 

Implement a BeanComparator with Jakarta Commons
Reflection is a powerful tool that can save time and effort. One way that it can be helpful is through the use of a BeanComparator.

BeanComparators are generic comparators that can act upon any Java Bean. With a good underlying bean reflection system, they can handle a bean with bean properties, arrays, collections, and maps.

If we have a java.util.List of Java Beans of type Person—where Person has an age that's an Integer, a name that's a String, and a country that's a Country bean (which itself has a String name)—we can sort it anyway we want with a BeanComparator.

Some examples:
 
List people = ...; // list of Person objects


//sort by age
BeanComparator comp = new BeanComparator("age");
Collections.sort(list, comp);


//sort by name
BeanComparator comp = new BeanComparator("name");
Collections.sort(list, comp);


//sort by country name
BeanComparator comp = new BeanComparator("country.name");
Collections.sort(list, comp);

 

There is no need to write a PersonComparator with lots of property options to sort by . Instead, a single BeanComparator class takes care of it all.

The underlying Reflection API handles all of the magic. Listing A is an example of a simple BeanComparator built on top of the Jakarta CommonsBeanUtils project:

The exception handling in this example has been simplified, and it’s assumed that the bean property to be compared implements Comparable, via the use of the ComparableComparator in the Jakarta Commons Collections project.

Editor's Picks

Free Newsletters, In your Inbox