Swing JTables of Java by default does not handle frequent updates and a huge number of columns and rows. I created a lighted version of JTable called FastJTable based on the code of the Java Christmas Tree.
This implementation is pretty faster when handling huge amounts of data. Consider taking a look at how the memory works if this is your use case.
/** * Based on Sun's CTTable (Christmas Tree): * https://java.sun.com/products/jfc/tsc/articles/ChristmasTree/ * * @author marias */ import java.awt.Component; import java.awt.Container; import java.awt.Graphics; import java.awt.Point; import java.awt.Rectangle; import javax.swing.CellRendererPane; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.JViewport; import javax.swing.plaf.basic.BasicTableUI; import javax.swing.table.TableModel; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; /** * Based on CTTable from Christmas Tree: * https://java.sun.com/products/jfc/tsc/articles/ChristmasTree/ * * @author marias marias@emergya.es */ public class FastJTable extends JTable { private static final Log log = LogFactory.getLog(FastJTable.class); private static final long serialVersionUID = -3218140266706898440L; private JScrollPane scrollPane; public FastJTable(TableModel model) { super(model); } public void updateUI() { super.updateUI(); setUI(new FastTableUI(this)); } private static class FastTableUI extends BasicTableUI { public FastTableUI(FastJTable table) { super(); installUI(table); } @Override public void installUI(JComponent c) { // Overriden to install our own CellRendererPane super.installUI(c); c.remove(rendererPane); rendererPane = new FastCellRendererPane(); c.add(rendererPane); } } /** * FastCellRendererPane overrides paintComponent to NOT clone the Graphics * passed in and NOT validate the Component passed in. This will NOT work if * the painting code of the Component clobbers the graphics (scales it, * installs a Paint on it...) and will NOT work if the Component needs to be * validated before being painted. */ private static class FastCellRendererPane extends CellRendererPane { private static final long serialVersionUID = 4811773663334451913L; private JViewport viewport; public FastCellRendererPane() { super(); } // Can be ignored, we don't exist in the containment hierarchy. public void repaint() { } @Override public void paintComponent(Graphics g, Component c, Container p, int x, int y, int w, int h, boolean shouldValidate) { try { if (c == null || !isVisible(new Rectangle(x, y, w, h))) { log.trace("No lo pintamos (" + c + ")"); return; } // if (p != null) { // Color oldColor = g.getColor(); // g.setColor(p.getBackground()); // g.fillRect(x, y, w, h); // g.setColor(oldColor); // } if (c.getParent() != this) { this.add(c); } c.setBounds(x, y, w, h); // As we are only interested in using a JLabel as the renderer, // which does nothing in validate we can override this to do // nothing, if you need to support components that can do // layout, // this will need to be commented out, or conditionally // validate. if (!(c instanceof JLabel)) c.validate(); // JComponent jc = (c instanceof JComponent) ? (JComponent) c // : null; // jc.setDoubleBuffered(true); // Don't create a new Graphics, reset the clip and translate // the origin. Rectangle clip = g.getClipBounds(c.getBounds()); g.clipRect(x, y, w, h); g.translate(x, y); c.paint(g); g.translate(-x, -y); g.setClip(clip.x, clip.y, clip.width, clip.height); c.setBounds(-w, -h, 0, 0); } catch (Throwable t) { log.error("Error al pintar el componente de la tabla ", t); } } /** * We only paint the visible parts of the JTable. * @param rectangle visible * @return if it has to be painted on screen */ public boolean isVisible(Rectangle rectangle) { if (viewport == null) return true; Rectangle visRect = viewport.getViewRect(); int xmin = ((Double) rectangle.getMinX()).intValue(); int ymin = ((Double) rectangle.getMinY()).intValue(); int xmax = ((Double) rectangle.getMaxX()).intValue(); int ymax = ((Double) rectangle.getMaxY()).intValue(); return (visRect.contains(new Point(xmin, ymin)) || visRect.contains(new Point(xmax, ymin)) || visRect.contains(new Point(xmin, ymax)) || visRect .contains(new Point(xmax, ymax))); } } }