搜索节点并保持树中的路径(parent-> child)不变

时间:2018-04-06 05:42:24

标签: java

我正在尝试根据搜索查询搜索子节点。我还需要将他们的父母(路径)留在树上。我在迭代和过滤已填充父母和孩子的完整树时遇到困难。搜索查询将匹配以下类的nodeName属性。社区中的某个人能够帮助我编写一个代码来搜索节点并保持他们的子路径完整但不保留父路径。

我的TreeNode类

public class TreeNodeDTO {

/** The id. */
private String id;

/** The nodeName. */
private String nodeName;

/** The children. */
private List<TreeNodeDTO> children;

//setters and getters
}

以及搜索节点并将其子节点保留在路径中的搜索方法。

public List< TreeNodeDTO > searchObject( String search ) {
    if ( getNodeName() != null && getNodeName().toLowerCase().contains( search.toLowerCase() ) ) {
        return Arrays.asList( this );
    }
    ArrayList< TreeNodeDTO > resultList = new ArrayList<>();
    if ( getChildren() != null ) {
        for ( TreeNodeDTO child : getChildren() ) {
            resultList.addAll( child.searchObject( search ) );
        }
    }
    return resultList;
}

上面的方法返回下面的树以进行以下搜索

搜索查询:&#34; TestProject&#34;

TestProject
        |
        TestChild

我正在努力以下列形式获得结果:

Project
  |
  SubProject
      |
      DataProject
           |
            TestProject
                |
                 TestChild

2 个答案:

答案 0 :(得分:0)

public class TreeNodeDTO {

    /** The id. */
    private String id;
    private TreeNodeDTO parent;

    /** The nodeName. */
    private String nodeName;

    /** The children. */
    private List<TreeNodeDTO> children;

    //setters and getters
    public List< TreeNodeDTO > searchObject( final String search ) {
        final ArrayList< TreeNodeDTO > resultList = new ArrayList<>();
        final Stack<TreeNodeDTO> candidates = new Stack<>();
        candidates.push( this );
        while ( !candidates.isEmpty() )
        {
            final TreeNodeDTO candidate = candidates.pop();
            if ( StringUtils.equalsIgnoreCase( search, candidate.getNodeName() ) )
            {
                resultList.add( candidate );
            }
            candidate.getChildren().forEach( child -> candidates.push( child ) );
        }
        return resultList;
    }

    /**
     * @return the id
     */
    public String getId()
    {
        return id;
    }

    /**
     * @param id the id to set
     */
    public void setId( final String id )
    {
        this.id = id;
    }

    /**
     * @return the parent
     */
    public TreeNodeDTO getParent()
    {
        return parent;
    }

    /**
     * @param parent the parent to set
     */
    public void setParent( final TreeNodeDTO parent )
    {
        this.parent = parent;
    }

    /**
     * @return the nodeName
     */
    public String getNodeName()
    {
        return nodeName;
    }

    /**
     * @param nodeName the nodeName to set
     */
    public void setNodeName( final String nodeName )
    {
        this.nodeName = nodeName;
    }

    /**
     * @return the children
     */
    public List<TreeNodeDTO> getChildren()
    {
        return children;
    }

    /**
     * @param children the children to set
     */
    public void setChildren( final List<TreeNodeDTO> children )
    {
        this.children = children;
    }
}

然后

TreeNodeDTO current = resultList.get(i);
while ( current != null ) {
    current = current.getParent();
    // Do what you want with the tree heirarchy
}

答案 1 :(得分:0)

您必须找到正确的路径并跟踪它。遍历树,保持您正在查看的TreeNodeDTO队列。如果分支不包含您要查找的节点,则从列表中删除分支根,然后放入下一个并搜索。让我们说你有这棵树:

Project
| SubProject1
| SubProject2
  |  TestChild1
  |  TestChild2

您正在寻找TestChild1,并且您以Project为根。您将Project作为队列中的第一个元素并浏览了它的TreeNodeDTO元素。将SubProject1放入队列并浏览其子节点。 SubProject1没有你想要的东西而且没有孩子。从队列中删除SubProject1并移至SubProject2。浏览SubProject2个孩子。找到TestChild1是您想要的那个,将其放入队列然后返回列表。如果树没有包含您要查找的节点,那么您将返回一个空队列。

我在TreeNodeDTO类中看到了一个复合模式,使用访问者模式来实现负责构建列表的操作。

<强>更新

快速解决方案:使用递归,这里是代码:

public class FindNodeRecursively {

  private boolean found = false;

  public void find(String name, TreeNodeDTO tree, Queue<TreeNodeDTO> queue) {
    queue.add(tree);
    if (tree.getId().equals(name)) {
        found = true;
    } else {
        for (TreeNodeDTO child : tree.getChildren()) {
            find(name, child, queue);
            if (found)
                break;
        }
        if (!found)
            queue.remove();
    }
  }
}

再次,看看compositevisitor模式以及如何将它们组合在一起。