2016-05-30 8 views
1

フォルダ構造の表現など、ツリー内でソートする必要のある数百のアイテムがあるとします。Javaでenum形式のツリーを作成するには?

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

これらの項目も、それぞれ手動で記述する必要があるため、コード内で静的に定義されます。

ここでは、ほとんどの場合、これらのアイテムをツリー内のパスでアクセスしています。私は文字列の識別で実装したくないのです。なぜなら、コード内の単純なタイプミスによる問題を避けたいからです(IDEは文字列内の構造体のタイプミスを助けないためです)。私は、クラスを実装することによって、これを達成でき

Item item = tree.a1.a2.b3; 

:たとえば、次のように:

//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"); 

マイツリー構造は、より堅牢になりしかし、すべての単一の項目のために、これは過度のように聞こえる。よりシンプルな方法が必要ですか?

私はちょうど1次元のリストでこれをやっていた場合、私は私が望むものを達成するために列挙型を使用することができます。

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; 

ツリーの列挙のような構造が存在する場合、それはいいだろうので。このような構造のアイテムへのパスはロックされていないようですが、私は雛形の列挙型を試しました。私は低レベルのアイテムにアクセスすることができます。

+1

列挙型の代わりに適切なクラスに問題がありますか?必要なのは 'Tree'と' Child'の2つのクラスだけで、 'Child'は他の' Child'クラスを参照することができます。 –

+0

"item item = tree.a1.a2.b3"はコンパイル時のものです。よりダイナミックなものがほしい。右? –

+0

@ cricket_007 *これは、1つのアイテムごとにクラスを実装することで達成できますが、これは過度の攻撃のようです。より簡単な方法が必要ですか?* –

答えて

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クラスを実装する必要はもちろんですが、EmptyTreeクラスを使用して、必要であれば、この設計は、簡単に二分木の厳格な使用に適合させることができます。

+0

'public class EmptyTree :ITree ':それは有効なJavaコードではありません、私はそれがC#だと思います。あなたのコードを修正してください。 –

+0

詳細な説明をいただきありがとうございますが、私はすでにこれに精通しており、他の解決策が見つからない場合はどうすればよいでしょうか。すべての項目はコード内で静的に定義されるため、これに起因する保守性の混乱を回避する方法はありません。代わりにコードからリストを移動すると、どこにいてもそれを維持しています。 – EJS

+0

@SeanPatrickFloyd私に知らせてくれてありがとう!私は最近、JavaよりもはるかにC#を行ってきました。 – SamTebbs33

0

これをJavaで実装するには満足できる方法はありません。

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

これらのクラスのすべてがgetChild()メソッドを実装し、共通の基本クラスから継承することができます:

1つのオプションは、すべてのアイテムのために別のクラスを持っていると、種類によってそれらにこのようなものを参照するだろう。

これはコンパイル時には安全ですが、実装するのも面倒です。 ScalaやGroovyのようなDSLに優しい言語を使うと、これはずっと苦痛を軽減します。

関連する問題