如何在java中创建树型对象? [复制]

Posted

技术标签:

【中文标题】如何在java中创建树型对象? [复制]【英文标题】:How to create a tree-type object in java? [duplicate] 【发布时间】:2016-01-26 08:14:07 【问题描述】:

我一直想知道创建在列表中包含列表的对象的最佳实践是什么。假设我有这种对象:

    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[])

【问题讨论】:

几乎是一个重复,但 OP 询问的是创建树,而不是结构本身。看起来很不一样。 【参考方案1】:

您可能想看看复合模式。 简而言之,这是在 Object A 持有 Object A 的集合时使用的。

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

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

至于创建部分,在这种情况下,我通常会使用工厂或构建器,但具体实现会有所不同。假设你有一个 2d 数组 if items,并且你想根据这个数组创建这些节点。

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 层的结构。递归方法更可取。您可以创建一个系统,其中 build 调用 build n 次,以创建您想要的深度。问题在于获取数据,为了使其工作,数据必须已经在正确的结构中,但就像字符串一样。 如果您的字符串是动态生成的,以便构建器可以计算出数据,则可以使其工作。

【讨论】:

【参考方案2】:

我提出这个设计希望它能帮助你:

TreeElement iterface :通用树元素类型。 Item 实现 TreeElement iterface 的类:所以它可以是 key 表示树节点或树节点的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 集合中用于确定集合是否包含给定元素。

【讨论】:

【参考方案3】:

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

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 描述得非常详细)。

【讨论】:

以上是关于如何在java中创建树型对象? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在Java中将泛型对象作为方法参数传递? [复制]

如何在js中创建树视图

如何在 C# 中创建树视图首选项对话框类型的界面?

如何在颤振/飞镖中创建泛型类型的对象?

如何在 Java 中创建列表列表并添加任何类型的列表? [复制]

在java中创建树数据结构?