Because I am constantly busy working on something, I have never had time to actually put everything in words and pictures. But, since you got here, then you must have already seen some part of my work - and this is the way I’m talking.I'm 23, born in Romania, student at UPG Romania in software development field. I started from 0, mostly with basic stuff, and I’m evolving every day to an expert. I'm focused on freelancing projects, from small websites, to really heavy stuff. I know that I look and act differently from most developers, but this is why you will love to work with me! Constantin has posted 42 posts at DZone. You can read more from them at their website. View Full User Profile

How to copy a static HashMap into a JTable

03.21.2011
| 5737 views |
  • submit to reddit

It was a sunny day with easy code and birds singing. But, suddenly a static HashMap (it could be non-static, also) wants to be copied into a two column JTable, keys on first column, and values on the second one. Well, the clouds start to press and before I notice it starts to rain … "with questions":

  • How to delete all rows of a JTable (I need this because sometimes I have to refresh the JTable for 0) ?
  • How to obtain the keys from the JTable by index, or similar?
  • How to add or insert the HashMap elements into JTable ?
Oh, sorry, I forgot to introduce you my static HashMap, nothing special, just a trivial one – the elements are irrelevant, therefore I’ll skip it:
public class MyMapHostClass {
...
public static Map myMap = new HashMap();
...
}

Afterwards, it proves to be a summer rain, warm and refreshing, because the answers jump up in a few minutes: delete all rows using a backward loop (or a nice trick) – both here, get all keys with the keySet method, and insert/add them into JTable with insertRow/addRow method. Well, I glue all these answers into lines code, and get this:
...
DefaultTableModel  model = (DefaultTableModel) jTable.getModel();
...
//remove all rows
model.getDataVector().removeAllElements();
...
//get all keys – notice the static effect, you can use it for non-static HashMap either
Set keys = MyMapHostClass.myMap.keySet();

//get an Iterator over keys
Iterator iteratorKeys = keys.iterator();

//put them into jTable
while (iteratorKeys.hasNext()) {
     String key = (String) iteratorKeys.next();
     //insert on first position by pushing down the existing rows
     model.insertRow(0, new Object[]{key, MyMapHostClass.myMap.get(key)});
     //append at the end
     model.addRow(new Object[]{key, MyMapHostClass.myMap.get(key)});
     }


Done! Now, is still raining, but … I’m singing in the rain!

From http://e-blog-java.blogspot.com/2011/03/how-to-copy-static-hashmap-into-jtable.html

Published at DZone with permission of its author, Constantin Alin.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Tags:

Comments

Gervais Blaise replied on Mon, 2011/03/21 - 2:47am

That's bad. Calling [insert|add]Row(..) will trigger an event that your JTable will use to redraw itself. You will have a better code with a custom TableModel who use your map or a copy of it and thus you can trigger TableRowsInserted when your model is loaded.

Attila Király replied on Mon, 2011/03/21 - 5:04am

You should use entrySet() instead of keySet()+get() to iterate over the map.

Walter Laan replied on Mon, 2011/03/21 - 5:18am

And to clear a DefaultTableModel, call setRowCount(0) so it fires the correct event (your way doesn't).

If you don't want a custom TableModel, you should build a new data vector and set it once with setDataVector) so only one event is fired.

Freddy Guime replied on Mon, 2011/03/21 - 8:43am

Hm, I don't think this is the best way to do it, seems messy inserting rows for a map change, and there are the issues of ordering (a hashmap doesn't have any policy on ordering).
I think it would be better to :
 - Use a LinkedHashMap (the order of the keys are guaranteed)
 - Implement a model using the LinkedHashMap as a backing for the model.
 - Lastly, threading issues have to be taken into account. If the linkedHashMap is
 not modified outside of the EDT, then using map.getSize()  for getRowCount is sufficient.

import javax.swing.table.AbstractTableModel;
import java.util.LinkedHashMap;


/**
 * Created by IntelliJ IDEA.
 * User: fguime
 * Date: 3/21/11
 * Time: 8:28 AM
 * MapTableModel
 */
public class MapTableModel extends AbstractTableModel {
    LinkedHashMap model;

    public MapTableModel(LinkedHashMap model) {
        this.model = model;
    }

    public int getRowCount() {
        return model.size();
    }

    public int getColumnCount() {
        return 2;
    }

    public String getColumnName(int columnIndex) {
        switch (columnIndex) {
            case 0:
                return "Key";
            case 1:
                return "Value";
        }
        return null;
    }

    public Class<?> getColumnClass(int columnIndex) {
        return String.class;
    }

    public boolean isCellEditable(int rowIndex, int columnIndex) {
        return false;
    }

    public Object getValueAt(int rowIndex, int columnIndex) {
        Object[] objects = new Object[model.size()];
        model.keySet().toArray(objects);
        Object key = objects[rowIndex];
        Object value = model.get(key);
        switch (columnIndex) {
            case 0:
                return key;
            case 1:
                return value;
        }

        return null;
    }

}

Couple of caveats: The getValueAt might not be as efficient as it populates an array on every call. Depending on the context this can be acceptable. More efficiency would be done by locally caching the list and then having a method to invalidate/reload the map.

- It assumes that the changes in the map are done in the EDT (not thread safe) , and
- It also assumes that when the map is changes, a fireTableDataChanged() event will be fired.

Michael Schnell replied on Mon, 2011/03/21 - 11:51am

You should consider using Glazed Lists to build your table model.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.