如何在Java中创建枚举式树?

时间:2016-05-30 15:24:01

标签: java enums

假设我有几百个需要在树中排序的不同项目,例如某些文件夹结构的表示。

           a1
          / | \
        a2 b2 c2
       / |  |
     a3 b3  c3

这些项目也将在代码中静态定义,因为每个项目都必须手动描述。

现在说我将主要通过它在树中的路径访问这些项目。我不想用字符串标识来实现它,因为我希望避免在我的代码中使用简单的拼写错误导致的问题(因为IDE不会帮助解决字符串中的结构错别字)。例如:

//Any typo inside the Strings would be ignored by the IDE.
Item item = tree.getChild("a1").getChild("a2").getChild("b3");

或者:

Item item = tree.get("a1\\a2\\b3");

如果我可以简单地执行以下操作,我的树结构会变得更强大:

Item item = tree.a1.a2.b3;

我可以通过为每个项目实现一个类来实现这一点,但这听起来有点过分。必须有一个更简单的方法吗?

如果我只使用一个列表进行此操作,我可以使用枚举来实现我想要的目标:

public enum Item {
    A1(1, "Description1"),
    A2(2, "Description2"),
    A3(3, "Description3");

    int prop1;
    String prop2;
    Item(int prop1, String prop2) {
        this.prop1 = prop1;
        this.prop2 = prop2;
    }
}

Item item = Item.A3;

如果树存在类似枚举的结构,那就太好了。我尝试了一些重要的枚举,但是这种结构中的项目路径似乎并未被锁定。我只能通过它的名字来访问一个低级别的项目而没有其余的路径。

2 个答案:

答案 0 :(得分:0)

为每个可能的项目实现枚举元素是疯狂的,并且根本不可维护或可扩展。为什么不创建一个模拟树结构的简单Tree类,并且可以存储所需的任何数据类型?

public class Tree<T> implements ITree<T> {

    public final T value;
    private List<ITree<T>> children;

    public Tree(T value) {
        this.value = value;
    }

    @Override
    public void addChild(ITree<T> child) {
        if(this.children == null) this.children = new LinkedList<T>();
        this.children.add(child);
    }

    @Override
    public ITree<T> getChild(int i) {
        return children.get(i);
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public T getValue() {
        return value;
    }

}

public class EmptyTree<T> implements ITree<T> {

    @Override
    public void addChild(ITree<T> child) {

    }

    @Override
    public ITree<T> getChild(int i) {
        return null;
    }

    @Override
    public boolean isEmpty() {
        return true;
    }

    @Override
    public T getValue() {
        return null;
    }

}

interface ITree<T> {
    public void addChild(ITree<T> child);
    public ITree<T> getChild(int i);
    public T getValue();
    public boolean isEmpty();
}

ITree<String> tree = new Tree<String>("a1");
tree.addChild(new Tree<String>("a2"));
tree.addChild(new EmptyTree<String>());
String rootVal = tree.getValue(); // "a1"
String childVal = tree.getChild(0).getValue(); // "a2"
boolean child2Val = tree.getChild(1).isEmpty(); // true

由于子项存储在列表中,当然没有必要实现EmptyTree类,但如果需要使用{{1},这个设计可以很容易地适应二进制树的严格使用}。class。

答案 1 :(得分:0)

在Java中没有令人满意的方法来实现它。

一个选项是为每个项目设置一个单独的类,并按类型引用它们,如下所示:

Item item = tree.getChild(A1.class).getChild(A2.class).getChild(B3.class);

所有这些类都可以从实现getChild()方法的公共基类继承。

虽然这是编译时安全的,但实现它也是一个巨大的麻烦。使用像Scala或Groovy这样的DSL友好语言可以减少痛苦。