如何在java中创建树型对象?

时间:2016-01-26 08:14:08

标签: java tree nested

我一直想知道创建列表中列表内列表的对象的最佳做法是什么。让我说我有这样的对象:

    root = new CarrierTreeNode(null, 
            new CarrierTreeNode[] {
                new CarrierTreeNode(new CarrierTreeItem("item1"), new CarrierTreeNode[] {
                    new CarrierTreeNode(new CarrierTreeItem("item1.1"))
                }),
                new CarrierTreeNode(new CarrierTreeItem("item2"), new CarrierTreeNode[] {
                    new CarrierTreeNode(new CarrierTreeItem("item2.1"))
            })
    });

我希望动态生成它,并动态访问和修改其中的列表/数组。这有设计模式吗? 谢谢。

为了更清楚,这里使用的构造函数是这样的:node(item,node [])

3 个答案:

答案 0 :(得分:2)

您可能想要查看复合模式。 简而言之,当对象A拥有对象A的集合时使用它。

这种模式/数据结构允许简单的递归行为。

有很多来源,所以如果这还不够,可以去google获取更多信息,但这是一个开始: https://en.wikipedia.org/wiki/Composite_pattern

至于创作部分,我通常在这种情况下使用工厂或制造商,但确切的实施方式会有所不同。假设您有一个2d数组,如果是项目,并且您想根据此数组创建这些节点。

public class NodeBuilder{
    public CarrierTreeNode build(String[][] items){
        CarrierTreeNode node = new CarrierTreeNode(null);
        for(int i = 1; i < items.length; i++){
           CarrierTreeNode nextNode = new CarrierTreeNode(new CarrierTreeItem(items[i][0]));
           node.addNextNode(nextNode);
           for(int j = 1; j < items[i].length; j++)
               nextNode.addNextNode(new CarrierTreeItem(items[i][j]));
        }
        return node;
    }
}

这显然只适用于3层结构。递归方法更可取。您可以创建一个构建调用构建n次的系统,以创建所需的深度。问题在于获取数据,为了使其工作,数据必须已经在正确的结构中,但就像字符串一样。 如果您的字符串是动态生成的,那么构建器可以找出数据,就可以使它工作。

答案 1 :(得分:1)

我建议这个设计希望它能帮到你:

  • TreeElement iterface:泛型树元素类型。
  • Item实现TreeElement iterface的类:所以它可以是一个 树节点的或树节点的
  • Node类,它也可以实现TreeElement接口 是基本节点或密钥的值。

这是实施:

interface TreeElement {

    enum ElementType {
        NODE, ITEM
    };

    public TreeElement getElement(Item item);

    public Node addElement(Item item, TreeElement element);

    public ElementType getType();

}

class Item implements TreeElement {

    String name;

    public Item(String name) {
        super();
        this.name = name;
    }

    @Override
    public TreeElement getElement(Item item) {
        return null;
    }

    @Override
    public ElementType getType() {
        return ElementType.ITEM;
    }

    @Override
    public Node addElement(Item item, TreeElement element) {
        return null;
    }

    @Override
    public String toString() {
        return "Item [" + name + "]";
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Item other = (Item) obj;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }

}

class Node implements TreeElement {

    Map<Item, TreeElement> map;

    {
        map = new HashMap<>();
    }

    @Override
    public TreeElement getElement(Item item) {
        return map.get(item);
    }

    @Override
    public ElementType getType() {
        return ElementType.NODE;
    }

    public Node addElement(Item item, TreeElement element) {
        this.map.put(item, element);
        return this;
    }

    @Override
    public String toString() {
        return "Node " + map + " ";
    }

}

测试代码:

Node node = new Node();
Item item = new Item("Item 1");
node.addElement(item, new Node().addElement(new Item("Level 1"), new Item("Item 1")));

System.out.println(node);
//Print : Node {Item [Item 1]=Node {Item [Level 1]=Item [Item 1]} } 

TreeElement element = node.getElement(item);

if (element.getType().equals(ElementType.NODE)) {
    element.addElement(new Item("Level 2"), new Node().addElement(new Item("Item 2.1"), new Item("Item 2.2")));
}

System.out.println(node);
//Print : Node {Item [Item 1]=Node {Item [Level 1]=Item [Item 1], Item [Level 2]=Node {Item [Item 2.1]=Item [Item 2.2]} } } 

重要提示: equals()hashcode()对示例的行为至关重要,尤其是equals()。它们在Map集合中用于确定集合是否包含给定元素。

答案 2 :(得分:0)

大多数简单的树节点实现必须包含一个用于存储数据的字段和自己子节点的列表。

public class Node<T> {

    private T data;
    private List<Node> list = new LinkedList<>();

    public Node(){}

    public Node(T data){
        this.data = data;
    }

    public List<Node> getChildList() {
        return list;
    }

    public void setData(T data) {
        this.data = data;
    }

    public T getData() {
        return data;
    }
}

这个类已经准备好构建简单的树结构了:

Node<String> root = new Node<String>("Stark");
root.getChildList().add(new Node<String>("Benjen"));

Node<String> eddard = new Node<String>("Eddard");
root.getChildList().add(eddard);
eddard.getChildList().add(new Node<String>("Arya"));

这种实施最简单但不是最好的。经典树节点提供有关父节点和兄弟节点的信息,内部递归搜索的方法,循环引用的控制以及许多其他内容(wiki描述它非常详细)。