Java TreeNode:如何防止getChildCount进行昂贵的操作?
我正在写一棵Java树,其中树节点可能需要花费很长时间才能计算出子节点(在这种情况下,这是一个文件系统,其中可能存在网络超时,无法从连接的驱动器中获取文件列表)。
我发现的问题是这样的:
- 在用户明确要求打开树的特定分支之前,将调用" getChildCount()"。我相信这样做是为了让
JTree
知道是否在节点旁边显示一个+图标。 - 要从
getChildCount()
中获得准确的孩子数,可能需要执行可能耗资巨大的操作 - 如果我伪造
getChildCount()
的值,则在请求枚举子节点之前,树仅为该多个子节点分配空间。 (如果我返回" 1",尽管有更多的孩子,我只会看到列出的一个孩子)
对孩子进行枚举可能既昂贵又费时,我可以接受。但是我不满意getChildCount()
需要知道孩子的确切数目。
有什么办法可以解决这个问题?
补充:另一个问题是,如果其中一个节点代表一个软盘驱动器(多么古老!),将在用户请求其文件之前对该驱动器进行轮询;如果驱动器中没有磁盘,则会导致系统错误。
更新:不幸的是,实现TreeWillExpand
监听器不是解决方案。这样可以否决扩展,但是显示的节点数仍然受TreeNode.getChildCount()返回的值的限制。
解决方案
我不确定它是否完全适用,但是最近我通过预先计算通常需要遍历子级列表的方法的答案来解决慢树的问题。我只会在添加,删除或者更新子级时重新计算它们。在我的情况下,某些方法将必须递归地沿着树走,以找出诸如"为每个节点存储多少字节"之类的事情。
如果我们需要大量访问数据结构的特定功能,而该功能的计算成本很高,则可能需要对其进行预先计算。
对于TreeNodes,这意味着TreeNodes必须存储其子级计数。为了更详细地解释它,当我们创建节点n0时,该节点的子计数(cc)为0。将节点n1添加为该节点的子节点时,我们将n1.cc + cc ++`。
棘手的是删除操作。我们必须保留与父级的反向链接,并向上层次结构减去当前节点的" cc"。
如果我们只想为节点提供" hasChildren"功能或者覆盖" getChildCount",则布尔值可能就足够了,并且在删除时不会强迫我们向上浏览整个层次结构。或者,我们可以删除反向链接,而只是说我们在删除操作上失去了精确度。实际上,TreeNode
接口不会强制我们提供删除操作,但是我们可能还是想要一个。
好吧,那是交易。为了提供预先计算的精确值,我们将必须保留某种反向链接。如果不这样做,最好调用方法" hasHadChildren"或者更有趣的" isVirgin"。
http://java.sun.com/docs/books/tutorial/uiswing/components/tree.html#data
向下滚动一点,那里有关于如何为jtree创建延迟加载节点的确切教程,并附带示例和文档
解决方案包括以下几部分:
- 就像Lorenzo Boccaccia所说的那样,使用TreeWillExpandListener
- 另外,需要在树上调用nodesWereInserted,因此将显示适当数量的节点。看到这个代码
- 我已经确定,如果我们不知道子计数,则TreeNode.getChildCount()需要至少返回1(它不能返回0)