Archive for the ‘Swing’ Category

The Pair class

Saturday, January 20th, 2007

This article describes a little utility class that I have found very useful in different occasions.
You may have already seen the Pair class in other languages or in libraries without realizing how helpful it can be in Java.

The Pair class holds two objects, first and second. first defines the behavior and second holds a reference to an associated object:

  • The toString(), equals() and hashCode() methods return the values of the first element
  • Pair implements Comparable and the compareTo() returns the comparison of the first elements.
public class Pair implements Comparable {
    public Object first;
    public Object second;

    public Pair() {
    }

    public Pair(Object first, Object second) {
        this.first = first;
        this.second = second;
    }

    public Object getFirst() {
        return first;
    }

    public void setFirst(Object first) {
        this.first = first;
    }

    public Object getSecond() {
        return second;
    }

    public void setSecond(Object second) {
        this.second = second;
    }

    public String toString() {
        return first.toString();
    }

    public boolean equals(Object that) {
        return that.equals(first);
    }

    public int hashCode() {
        return first.hashCode();
    }

    public int compareTo(Object thatObject) {
        final Pair that = (Pair) thatObject;
        final Comparable thisComparable = (Comparable) this.first;
        final Comparable thatComparable = (Comparable) that.first;
        return thisComparable.compareTo(thatComparable);
    }
}

Replacement for CellRenderer

When you add you own objects to a JList or JTree, Swing uses the toString() method of your object to get the label to display.

This is not always convenient. You may not be the owner of the object. If you want to display a list of java.awt.Color objects for example, you do not have the liberty of adding a toString() method to the Color class.
You may want to use the toString() method for you own debugging purpose. Most debuggers today allow you to display the toString() value in the data window.
Sometimes the same object will be displayed differently depending on the context.

The alternative would be to write a CellRenderer but you know the cost of a class and writing a cell renderer just to define the label of the objects might be an overkill.

This is where the Pair class becomes handy: add Pairs to the list. The first element will be the label and the second is your object.
Since Pair implements Comparable, it can even be used to sort the list.
The following example illustrates how to add objects to a JList but using a different text than the toString() of the object. The example takes advantage of the HTML capability of the Swing components to show the last name in bold.

        List<Person> persons = Arrays.asList(
                new Person("Adrian", "Monk"),
                new Person("Disher", "Randall"),
                new Person("Leland", "Stottlemeyer"),
                new Person("Sharona", "Fleming"),
                new Person("Natalie", "Teeger")
        );

        final Pair[] temp = new Pair[persons.size()];
        for (int i = 0; i < persons.size(); i++) {
            final Person person = persons.get(i);
            final String label = "&lt;HTML&gt;&lt;B&gt;" +
                                 person.getLastName() +
                                 "&lt;/B&gt;, " +
                                 person.getFirstName();
            temp[i] = new Pair(label, person);
        }
        Arrays.sort(temp);

        final JList list = new JList(temp);
        final JLabel label = new JLabel();
        final JPanel panel = new JPanel(new BorderLayout());
        panel.add(list);
        panel.add(label, BorderLayout.SOUTH);

        list.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                if (!e.getValueIsAdjusting()) {
                    final Pair selectedPair = (Pair) list.getSelectedValue();
                    final Person person = (Person) selectedPair.second;
                    label.setText("Your selection: " +
                                  person.getFirstName() +
                                  " " +
                                  person.getLastName());
                }
            }
        });

And here is what it looks like:

Pair Demo

The source code is available here.