Generate "explorer tree" in Java efficiently (not using recursion)
I have a question which could be language-agnostic but for this particular implementation I'm using Java. It is possible and relatively trivial to list the folders in a directory - using a function like this:
private DefaultMutableTreeNode GenerateFSTree(File f)
{
int i = 0;
File[] Children = f.listFiles();
DefaultMutableTreeNode x = new DefaultMutableTreeNode(f.getName());
if ( Children != null )
{
for ( i = 0; i < Children.length; i++ )
{
File f_cur = Children[i];
if (
f_cur.isDirectory() &&
( this.DisplayHidden || !f_cur.isHidden() )
)
{
x.add(GenerateFSTree(f_cur));
}
}
}
return x;
}
As you can see this makes heavy use of recursion to evaluate the filesystem and what you end up with is a tree of DefaultMutableTreeNode
items.
Now my question is - is there a faster way to do this? There must be, because this is slow. Try executing this on /
and it takes forever. Yet if I use say Nautilus or the built-in Java File selection dialog, the tree renders instantly.
So my question is - how can I spee开发者_高级运维d this up?
Thanks
The normal way to do this is to only read a single directory at first. Any directories under that top level directory will not be read immediately. Instead a dummy node will be inserted under the directory tree node that is created. When the user expands the directory node the program then reads the relevant directory and then replaces the dummy node with nodes that reflect the contents of the directory.
take a look at this example
http://www.java2s.com/Code/Java/Swing-JFC/FileTree.htm
this treemodel will provide the filesystem structure to your jtree. the file system is only accessed when expanding a node... and initially for the root node. ;)
class FileTreeModel implements TreeModel {
protected File root;
public FileTreeModel(File root) { this.root = root; }
public Object getRoot() { return root; }
public boolean isLeaf(Object node) { return ((File)node).isFile(); }
public int getChildCount(Object parent) {
String[] children = ((File)parent).list();
if (children == null) return 0;
return children.length;
}
public Object getChild(Object parent, int index) {
String[] children = ((File)parent).list();
if ((children == null) || (index >= children.length)) return null;
return new File((File) parent, children[index]);
}
public int getIndexOfChild(Object parent, Object child) {
String[] children = ((File)parent).list();
if (children == null) return -1;
String childname = ((File)child).getName();
for(int i = 0; i < children.length; i++) {
if (childname.equals(children[i])) return i;
}
return -1;
}
public void valueForPathChanged(TreePath path, Object newvalue) {}
public void addTreeModelListener(TreeModelListener l) {}
public void removeTreeModelListener(TreeModelListener l) {}
}
usage
Jtree tree = new JTree(new FileTreeModel(new File("/")));
this model will prevent you from filling up your memory with DefaultTreeNodes and minimizes the access to the underlying filesystem.
精彩评论