【问题标题】:Search for nodes and keep their path(parent->child) in tree intact搜索节点并保持它们在树中的路径(父->子)完好无损
【发布时间】:2018-04-06 05:42:23
【问题描述】:

我正在尝试根据搜索查询搜索子节点。我还需要将他们的父母(路径)保留在树中。我在迭代和过滤填充了父母和孩子的完整树时遇到了困难。搜索查询将匹配以下类的 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;
}

Above 方法返回下面的树以供后续搜索

搜索查询:“TestProject”

TestProject
        |
        TestChild

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

Project
  |
  SubProject
      |
      DataProject
           |
            TestProject
                |
                 TestChild

【问题讨论】:

  • 您能否添加作为输入提供的完整树的结构?
  • @vastal 您的意思是已填充的完整树?如果是,那么在项目节点下还有另一个名为“testDemoProject”的子项目,并且它还有更多节点。但我需要像上面这样的过滤结果。

标签: java


【解决方案1】:
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
}

【讨论】:

  • 产生与我上面的代码相同的结果,即没有父母
【解决方案2】:

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

Project
| SubProject1
| SubProject2
  |  TestChild1
  |  TestChild2

您正在寻找TestChild1,并且您拥有Project 作为root。您将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 模式以及如何将它们组合在一起。

【讨论】:

  • 产生如此多不一致的结果
猜你喜欢
  • 2011-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-02
  • 2018-07-07
相关资源
最近更新 更多