这是数据库表结构(sybase):
create table cislite_favorites(
   favid   int  null,
   name   varchar(300)  null,
   type   char(1)  null,
   parent_favid   int  null,
   res_id   int  null,
   userid   smallint  null,
   order_num   int  null
)
create nonclustered index cislite_favoritesI1 on dbo.cislite_favorites( favid ASC)parent_favid是用于指向自身,代表其父节点的ID。但公司不希望使用数据库中的外键,而是希望用程序实现。
favid   name   type     parent_favid
68 D1 T -1
69 D2 T -1
71 D11 T 68
72 F1 F 68
73 F2 F 71
76 F3 F 69
79 D22 T 69
92 f111 F 79这些都只是一些测试数据。当parent_favid为-1时,则为根节点。
我目前的做法是一次性读入所有数据到一个List<FavoriteTreeNode>中,然后线性搜索FOR循环遍历这个LIST来组装成树。我觉得每次都要线性搜索效率比较低下。
关键组装代码代码
    /**
     * load the children of the nodes in the List
     * @param nodes the parent node List
     */
    private void loadChildren(List<FavoriteTreeNode> nodes) {
        for (FavoriteTreeNode node : nodes) {
            boolean isDirectory = false;
            FavoriteTreeNode current = node;
            for (FavoriteTreeNode tmp : sourceNodes) {
                if (isChild(current, tmp)) {
                    tmp.setParent(current);
                    current.addChild(tmp);
                    isDirectory = true;
                }
            }
            if (isDirectory) {
                sourceNodes.removeAll(current.getChildren());
                loadChildren(current.getChildren());
            }
        }
    }

解决方案 »

  1.   

    如果数据是从数据库里取出来的,那没办法。因为要得到实时的数据,只能遍历。
    另外,我觉得你的逻辑似乎有点问题:
    1.tmp.setParent(current);
    current.addChild(tmp); 
    这两行代码,我觉得应该在一个方法里完成。tmp的parent是current,那么current的child就肯定是tmp。就应该是一次操作。
    2.内层的for循环中,可能多次对isDirectory赋值。但是if(isDirectory)在循环结束后才进行。
    3.我认为isDirectory作为FavoriteTreeNode类的一个方法更合理。