Comments
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Cloud Expo on Google News


2008 West
DIAMOND SPONSOR:
Data Direct
SOA, WOA and Cloud Computing: The New Frontier for Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
GOLD SPONSORS:
Appsense
User Environment Management – The Third Layer of the Desktop
Cordys
Cloud Computing for Business Agility
EMC
CMIS: A Multi-Vendor Proposal for a Service-Based Content Management Interoperability Standard
Freedom OSS
Practical SOA” Max Yankelevich
Intel
Architecting an Enterprise Service Router (ESR) – A Cost-Effective Way to Scale SOA Across the Enterprise
Sensedia
Return on Assests: Bringing Visibility to your SOA Strategy
Symantec
Managing Hybrid Endpoint Environments
VMWare
Game-Changing Technology for Enterprise Clouds and Applications
Click For 2008 West
Event Webcasts

2008 West
PLATINUM SPONSORS:
Appcelerator
Get ‘Rich’ Quick: Rapid Prototyping for RIA with ZERO Server Code
Keynote Systems
Designing for and Managing Performance in the New Frontier of Rich Internet Applications
GOLD SPONSORS:
ICEsoft
How Can AJAX Improve Homeland Security?
Isomorphic
Beyond Widgets: What a RIA Platform Should Offer
Oracle
REAs: Rich Enterprise Applications
Click For 2008 Event Webcasts
SYS-CON.TV
Top Links You Must Click On


Java Design Patterns for Long Lists
Providing fast performance

In the late 1990s, a GUI design pattern emerged for choosing multiple objects from long lists. In GUI Design Essentials, Susan Weinschenk, Pamela Jamar, and Sarah Yeo called this the Selection Summary pattern. In "A Dual Listbox Selection Manager" by Steve Aube, it's also known as the Dual Listbox Selection interface. In The Java Look and Feel Guidelines, Advanced Topics, it is called the Add-and-Remove idiom.

The Add-and-Remove design pattern (shown in Figure 1) has many variations. One common enhancement is to provide "Move Up" and "Move Down" buttons to reorder the chosen list (see Figure 2). Sometimes the chosen list is displayed as a table to show additional information.

My previous article ("GUI Design Patterns," JDJ, Vol. 9, issue 7) showed how to optimize usability for this common GUI design pattern. This article shows how to optimize performance for this design pattern and other GUIs that display long lists.

Java Performance Patterns
For short lists, neither the JList or the JTable are likely to give performance problems; Java and Swing have been optimized many times over the years. If your lists contain thousands of objects though, there are some standard Java design patterns that optimize performance.

The key to all these performance patterns is to realize that the default list and table implementations are general purpose. To optimize performance, you want to bypass this general-purpose code by informing the JList or JTable of your application's specific needs.

Fix the Cell Size
For example, JLists by default assume that the objects they contain may be of varying sizes. If your application's objects are all the same size, you can inform the JList of this fact. It will then bypass its general-purpose, size-checking code. To fix the cell size, invoke either the setFixedHeight() and setFixedWidth() methods, or the setPrototypeCellValue() method. In "Advanced JList Programming," Hans Muller notes that setFixedHeight() and setFixedWidth() are useful to align a JList with another component. Otherwise, it's generally more convenient to use setPrototypeCellValue().

For the prototype cell value, use the value that is largest visually. If the maximum width is known, a prototype value can be assigned without looping over all the values, thus saving initialization time. Alternatively, if the application uses a monospace font, a fast loop can be written to check the string lengths of all values. Otherwise, to allow proportional fonts, anti-aliasing, and other issues, check the FontMetrics as in the code below.


   double width = 0;
   String prototype = "";
   FontMetrics fm = jList.getFontMetrics( jList.getFont());
   Graphics g = jList.getGraphics();
   for( int i = 0; ( i < values.length ); i++ )
   {  String s = values[ i ].toString();
      if( width < fm.getStringBounds( s, g ).getWidth())
      {  width = fm.getStringBounds( s, g ).getWidth();
         prototype = s;
      }
   }
   jList.setPrototypeCellValue( prototype );

Write a Custom Model
For many applications, fixing the cell size may provide all the performance boost you need. If it doesn't, the next step is to take advantage of Swing's flexible architecture.

Figures 3 and 4 show portions of the JList and JTable architectures. Both lists and tables allow you to replace their default models with custom models of your own. The only requirement is that your custom model implement the ListModel or TableModel interface.

The simplest way to do this is to extend AbstractListModel or AbstractTableModel. These classes provide management of listeners and events. Technically, to support the ListModel interface it is necessary to override only two methods in AbstractListModel:

public Object getElementAt( int i )
public int getSize()

Similarly, to support the TableModel interface it's necessary to override only three methods in AbstractTableModel:

public Object getValueAt( int row, int column )
public int getRowCount()
public int getColumnCount()

These methods support a ListModel or TableModel that is immutable: its contents can't be changed. For an application such as the Add-and-Remove pattern, the contents must be mutable. This requires extending the AbstractListModel with methods to add and remove values from the list:

public void addElement( Object o )
public void removeRElement( int i )

Similarly, the AbstractTableModel can be extended with methods to add and remove rows from the table.

public void addRow( Object[] row )
public void removeRow( int i )

Writing a custom model informs the Swing GUI control of your application's specific needs, causing it to bypass its general-purpose code. For example, both the DefaultListModel and the DefaultTableModel are Vector based. This means their accessor methods are synchronized. If your application doesn't require synchronization, it can be removed in the custom model, for example, by using an ArrayList instead of a Vector. A custom ListModel based on an ArrayList is shown in Listing 1.

For the Add-and-Remove pattern, a further performance boost can be obtained by realizing that the total number of objects never changes. Both Original and Chosen lists have a fixed maximum size, which is the sum of the number of objects in each. This means that a custom model does not need expandable storage, such as a java.util.Collection, so a more efficient array can be used instead. A custom TableModel based on an array is shown in Listing 2.

Finally, significant performance can be gained by adding methods to the custom model to process multiple objects. The custom ListModel of Listing 1 provides three methods to handle multiple objects:

public void addAll( Object[] objects )
public void clear()
public Object[] toArray()

In the DefaultListModel, to add 100 objects addElement() must be invoked 100 times. In the custom model, the addAll() method can be invoked only once. If an application operates on multiple objects, performance can almost always be improved by writing a custom model.

Can More Be Done?
For most applications, a custom model provides sufficient performance improvement. However, Swing provides another option using the same architectural pattern. As shown in Figures 5 and 6, JList and JTable rely on renderers to display their contents.

Just as the custom model replaced the default model, a custom renderer can replace the default renderer. The only requirement is that the custom renderer implement the ListCellRenderer or TableCellRenderer interface.

The performance boost from a custom renderer is roughly proportional to the number of objects being rendered. If your application displays only a few objects, as in the Add-and-Remove pattern, this performance boost is not significant. A better use of a custom renderer is given by Steve Wilson and Jeff Kesselman in Java Platform Performance: Strategies and Tactics. Their example displays a sparse table that derives a significant performance boost because the empty cells don't need to be rendered at all.

Some highly specialized applications require more specialized performance patterns. Hans Muller notes that internally JList uses the toString() method to convert objects to strings. If the application does not need this generality, the conversion time can be saved by building a custom model around the String class rather than the Object class.

In Christmas Tree Applications Scott Violet and Kathy Walrath give a fine and detailed example using a custom renderer and other performance patterns. Their code produces fast performance for frequently updated JTables. Patterns such as these are not usually needed, but they show the performance improvements that become possible when Swing is tailored to a specific application.

How Much Improvement Can We Expect?
Performance benchmarks for the Add-and-Remove pattern show that fixing the cell size is the most cost-effective performance pattern for JLists. Both JLists and JTables can achieve dramatic improvement from custom models, especially when processing multiple objects.

The benchmarks shown in Figures 7 and 8 and Tables 1-4 were run using JDK 1.4.1 under Mac OS X on a G4 CPU at 450MHz. Your mileage will vary, but these conclusions hold for most applications:

  • For a JList, fix the cell size.
  • For a long list or table, write a custom model.
  • For a specialized application, consider specialized design patterns such as a custom renderer.
Conclusion
The Add-and-Remove GUI design pattern enables users to choose multiple objects from long lists. Appropriate Java design patterns provide fast performance for this GUI and other applications.

Resources

  • Aube, S. (2000). "A Dual Listbox Selection Manager": www.codeguru.com/Cpp/controls/listbox/article.php/c4755
  • Muller, H. (2000). "Advanced JList Programming": java.sun.com/products/jfc/tsc/tech_topics/jlist_1/jlist.html
  • Sun Microsystems Inc. (2002). Java Look and Feel Design Guidelines: Advanced Topics. Addison-Wesley Professional: java.sun.com/products/jlf/at/book/Idioms6.html
  • Violet, S., and Walrath, K. (2002). "Christmas Tree Applications": java.sun.com/products/jfc/tsc/articles/ChristmasTree/
  • Weinschenk, S., Jamar, P., and Yeo, S. (1997). GUI Design Essentials. Wiley & Sons. p. 192, 206-207.
  • Wilson, S., and Kesselman, J. (2000). JAVA Platform Performance: Strategies and Tactics. Chapter 10: java.sun.com/developer/books/performance/
  • About Heman Robinson
    Heman Robinson is a senior developer with SAS Institute in Cary, N.C. He holds a BS in mathematics from the University of North Carolina and an MS in computer science from the University of Southern California. He has specialized in GUI design and development for 15 years and has been a Java developer since 1996.

    In order to post a comment you need to be registered and logged in.

    Register | Sign-in

    Reader Feedback: Page 1 of 1

    Enterprise Open Source Magazine Latest Stories . . .
    With Cloud Expo 2012 New York (10th Cloud Expo) just four months away, what better time to start introducing you in greater detail to the distinguished individuals in our incredible Speaker Faculty for the technical and strategy sessions at the conference... We have technical and st...
    AMD said late Tuesday that its chief sales officer Emilio Ghilardi had left the company and that CEO and president Rory Read is going to do his job while a replacement is sought. AMD didn’t say why Ghilardi left but it’s assumed Read wants his own people. Read is relatively new to th...
    During the lifespan of M3 (Monitis Monitor Manager) there has always been something lacking – timers. M3 execution procedure was outlined in this previous article. The execution mentioned in the latter was a one-time-execution, whereas server monitoring requires periodic invocati...
    Red Hat is putting its bought-in Gluster scale-out NAS storage technology, acquired in October, on the Amazon cloud. It’s styled Red Hat Virtual Storage Appliance for Amazon Web Services and other clouds are supposed to follow in short order.
    A new episode of the screencast series is now available at the OpenNebula YouTube Channel. This screencast demonstrates the new easily-customizable self-service portal for cloud consumers. Its aim is to offer a simplified access to shared infrastructure for non-IT end users. The scree...
    C12G Labs has just announced an update release of OpenNebulaPro, the enterprise edition of the OpenNebula Toolkit. OpenNebula 3.2, released two weeks ago, brings important benefits to cloud providers with a new easily-customizable self-service portal for cloud consumers, and builders w...
    Subscribe to the World's Most Powerful Newsletters
    Subscribe to Our Rss Feeds & Get Your SYS-CON News Live!
    Click to Add our RSS Feeds to the Service of Your Choice:
    Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
    myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
    Publish Your Article! Please send it to editorial(at)sys-con.com!

    Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


    SYS-CON Featured Whitepapers
    ADS BY GOOGLE