2016-05-30 11 views
1

Angenommen, ich habe ein paar hundert verschiedene Elemente, die in einem Baum sortiert werden müssen, wie zum Beispiel eine Darstellung einer Ordnerstruktur.Wie erstellt man einen Enum-Style-Baum in Java?

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

Diese Elemente werden auch statisch im Code definiert, da jeder manuell beschrieben werden muss.

Jetzt sagen Sie, dass ich auf diese Elemente meist über den Pfad im Baum zugreifen werde. Ich möchte es nicht mit String-Identifizierung implementieren, weil ich Probleme vermeiden möchte, die durch einfache Tippfehler in meinem Code verursacht werden (weil eine IDE nicht mit Tippfehlern der Struktur in Strings behilflich ist). Zum Beispiel wie folgt aus:

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

Oder:

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

Mein Baumstruktur wird robuster, wenn ich einfach etwas tun kann, wie:

Item item = tree.a1.a2.b3; 

ich dies durch die Implementierung einer Klasse erreichen könnte Für jeden einzelnen Artikel klingt das jedoch nach Overkill. Es muss einen einfacheren Weg geben?

Wenn ich dies mit nur einen einer dimentional Liste zu tun, kann ich Aufzählungen verwenden, um zu erreichen, was ich will:

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 wäre es schön, wenn es eine ENUM-ähnliche Struktur für Bäume vorhanden ist. Ich habe hiarchical enums ausprobiert, aber der Weg zu einem Gegenstand in einer solchen Struktur scheint nicht abgeschlossen zu sein. Ich kann auf ein Item auf niedriger Stufe zugreifen, nur nach seinem Namen ohne den Rest seines Pfades.

+1

Was stimmt nicht mit einer richtigen Klasse anstelle einer Enum? Alles, was Sie brauchen, sind zwei Klassen 'Tree' und' Child' und jedes 'Child' kann auf andere' Child' Klassen verweisen. –

+0

"Item item = tree.a1.a2.b3" ist eher eine Kompilierzeit Sache und ich denke, dass Sie etwas dynamischeres wollen. Recht? –

+0

@ cricket_007 * Ich könnte dies erreichen, indem ich für jedes einzelne Element eine Klasse implementiere, aber das klingt nach Overkill.Es muss einen einfacheren Weg geben? * –

Antwort

0

Das Implementieren eines Enum-Elements für jedes mögliche Element ist verrückt und ist überhaupt nicht realistisch wartbar oder skalierbar. Warum erstellen Sie nicht einfach eine einfache Tree Klasse, die die Struktur eines Baumes nachahmt und die jeden gewünschten Datentyp speichern kann?

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 

Da die Kinder in einer Liste gespeichert werden, ist es natürlich nicht notwendig, die EmptyTree Klasse zu implementieren, aber das Design leicht auf die strenge Verwendung von binären Bäumen angepasst werden könnte, wenn unter Verwendung der EmptyTree Klasse sein muss.

+0

'öffentliche Klasse EmptyTree : ITree ': Das ist nicht gültig Java-Code, ich vermute es ist C#. Bitte korrigieren Sie Ihren Code. –

+0

Vielen Dank für die detaillierte Beschreibung, aber ich bin bereits vertraut mit dieser und es wäre was ich tun würde, wenn ich keine andere Lösung finden könnte. Alle Elemente werden statisch im Code definiert, so dass es keine Möglichkeit gibt, das Wartbarkeits-Chaos zu umgehen. Wenn ich die Liste alternativ aus dem Code entferne, bin ich immer noch dabei, sie beizubehalten, wo auch immer sie ist. – EJS

+0

@SeanPatrickFloyd Danke, dass Sie mich wissen lassen! Ich habe in letzter Zeit viel mehr C# als Java gemacht. – SamTebbs33

0

Es gibt keine befriedigende Möglichkeit, dies in Java zu implementieren.

Eine Möglichkeit wäre, eine eigene Klasse hat für jedes Element und unter Bezugnahme auf sich nach Art, so etwas wie:

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

All diesen Klassen von einer gemeinsamen Basisklasse erben könnte, die die getChild() Methode implementiert .

Während dies Kompilierzeit sicher ist, wird es auch ein riesiger Aufwand, es zu implementieren. Mit einer DSL-freundlichen Sprache wie Scala oder Groovy wäre dies viel weniger schmerzhaft.

Verwandte Themen