简体   繁体   中英

How to create an enum-style tree in Java?

Say that I have a few hundred different items that needs to be sorted in a tree, like for example some representation of a folder structure.

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

These items will also be defined statically in the code as each one has to be described manually.

Now say that I will mostly be accessing these items by it's path in the tree. I don't want to implement it with string identification because I wish to avoid problems caused by simple typos in my code (because an IDE won't help out with typos of structure inside strings). For example like this:

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

Or:

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

My tree structure becomes more robust if I can simply do something like:

Item item = tree.a1.a2.b3;

I could accomplish this by implementing a class for every single item, however this sounds like overkill. There has to be a simpler way?

If I was doing this with just a one dimentional list, I could use enums to achieve what I want:

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;

So it would be nice if there exists an enum-like structure for trees. I tried out hiarchical enums however the path to an item in such a structure doesn't seem to be locked. I can access a low level item just by it's name without the rest of it's path.

Implementing an enum element for each possible item is mad and isn't at all realistically maintainable or scalable. Why don't you just make a simple Tree class that mimics the structure of a tree, and that can store any data type desired?

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

As the children are stored in a list, it is of course unnecessary to implement the EmptyTree class, but this design could be easily adapted to the strict use of binary trees if need be by using the EmptyTree class.

There is no satisfactory way of implementing this in Java.

One option would be to have a separate class for every item and referring to them by type, something like this:

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

All of these classes could inherit from a common base class that implements the getChild() method.

While this is compile-time safe, it will also be a huge hassle implementing it. Using a DSL-friendly language like Scala or Groovy would make this a lot less painful.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM