Monday, September 21, 2015

Sorting a Java ArrayList of SelectItem Objects

Recently I had a task where I needed to read all the names from several groups in the Name & Address Book.  I needed to get all the names sorted and unique for presenting in a Combobox.

In this post, I will show you how I did this, but more importantly I will show how I used the Java Collections Framework to my advantage.

In case you aren’t aware, the SelectItem object is the object type that Java Server Faces (thereby XPages) uses for the values of a Combo Box. It contains a value and a label, of which the label is what is shown and the value is what is saved.

Because the SelectItem does not implement the Comparator interface, you cannot easily sort an ArrayList of SelectItems. You could write your own sorting method if you like using the instructions outlined in this blog post. I considered this but then thought of an easier way to accomplish the same thing.

Here is what I did to solve this: Instead of creating just an ArrayList of SelectItems, I also created one of Strings. Strings of course are easily sortable since the String class does implement Comparator interface. Prior to sorting the list, I need to removed duplicates. To do this, I first create a HashSet and assign the values to it. A Set in java does not allow duplicates, so assigning all the values to the HashSet was the easiest way to remove the dupes. After this is done, I assign all the values back into the ArrayList and then sort the list. I then create an SelectItem ArrayList with the unique sorted values.

Note: This would be a lot more complicated if I needed my SelectItem object to have different Strings for Label and Value. I would probably use a HashMap instead of an ArrayList<String> if this was the case.

Code Example


public List<SelectItemgetUserList(String schema){ 
1  List<String> options = new ArrayList<String>(); 
List<SelectItemsortedOptions = new ArrayList<SelectItem>();

try { 
  Session session = getCurrentSession(); 
  Database nab = session.getDatabase(session.getCurrentDatabase().getServer(), "names");

if (nab.isOpen()) { 
View view = nab.getView("Groups"); 
if (view != null) { 
Document doc = view.getDocumentByKey("Group 1"true); 
if (doc != null) { 
Item item = doc.getFirstItem("Members"); 
Vector<String> v = item.getValues(); 
for(String person : v){ 
Name name = session.createName(person);  options.add(name.getCommon()); 
} 
doc.recycle(); 
item.recycle(); 
else { 
log.error("Group 1 cannot be opened."); 
} 
doc = view.getDocumentByKey("Group 2"true); 
if (doc != null) { 
Item item = doc.getFirstItem("Members"); 
Vector<String> v = item.getValues(); 
for(String person : v){ 
Name name = session.createName(person); 
options.add(name.getCommon()); 
} 
doc.recycle(); 
item.recycle(); 
else { 
log.error("Group cannot be found, or opened."); 
} 
……………… //get names from third group 
} 
else { 
log.error("Address Book is not found, or able to be opened."); 
} 
catch (NotesException e) { 
log.error("EXCEPTION in getUserList(): " + e.toString()); 
e.printStackTrace(); 
} 

Set<String> hs = new HashSet<String>();
hs.addAll(options); 
options.clear(); 
options.addAll(hs); 

Collections.sort(options); 

for(String person : options){  
SelectItem option = new SelectItem(); 
option.setLabel(person); 
option.setValue(person); 
sortedOptions.add(option); 
} 
return sortedOptions; 
}

Code Explanation using footnotes:


1  - Declare two ArrayLists, one for Strings, and one for SelectItems.

2  - The values of a multi-value field are returned as a Vector. For each item in the Vector, I assign the item into the String ArrayList

3 - This uses the Name class to get the formatted name. This is part of the original Notes API for java, and is quite useful.

4 -  This is where I pass the contents of the String ArrayList into a HashSet and then back again. All Sets in Java are not able to contain duplicate values. 

5 - After the duplicates are removed, then I sort the list. If you try to sort before removing duplicates it won't be sorted after changing to a Hashset and back. As you can see, sorting a String List is very easy using the Collections class.

6 -  Lastly, I convert the ArrayList of Strings into an ArrayList of SelectItems for use in my combo box.

Last Words


In Java the Collections Framework is super useful and one of the strengths of the language. If you are learning Java it would wise to pay special attention to knowing what it can do for you.  

Please check comments of this post for some great tips on how to improve on what I posted.