web-dev-qa-db-ja.com

なぜJava Collection Frameworkにはツリーとグラフが含まれていない

Java基本的なインターフェイスを含むコレクションフレームワーク:CollectionおよびMapに精通しています。フレームワークにツリーおよびグラフとして構造が含まれていない理由を知りたいどちらもCollectionのサブタイプと見なすことができます。

ところで、TreeSetはRed-Black Treeで実装されていることを知っています。ただし、TreeSetはツリーではなくSetであるため、フレームワークには実際のツリーはありません。

Frameworkに、基本的なコレクションであるTreeやGraphのような構造が含まれていないのはなぜかと思っています。両方ともCollectionのサブタイプと見なすことができます。

これはいい質問です。私はそれが単にスコープに要約されると思います。 Collections APIがクラスを提供するコア機能は次のとおりです。

  • 反復順序:リストとソートされたマップには反復順序が指定されていますが、ほとんどのセットには指定されていません。

  • duplicates:リストは重複を許可しますが、セットは許可しません

  • インデックス:リスト値は整数でインデックス付けされ、マップ値は他のオブジェクトでインデックス付けされます。

これにより、私たちは非常に遠くに行き、Joshua Blochらは、これらの3つの上に、より多くの機能豊富なコレクション(要素間の内部関係、多重度を持つセット、双方向マップなど)を実装できると主張したと仮定しますコア機能であるため、ライブラリの方が優れています。

26
aioobe

Java.utilパッケージには、あらゆる種類のデータを整理するためのデータ構造が含まれています。基本的にabstractデータ構造(ListSetMapなど)を扱います。メソッドと動作を介して定義されます(たとえば、Setには2回要素が含まれない、Listは順序を維持し、重複を許可するなど)。

開発者は、これらのデータ構造のどの実装を扱うデータの種類に最適かを自由に選択できます(HashSet vs. TreeSet/LinkedList vs.ArrayList /など) )。たとえば、セットとマップの場合、ハッシュベースの実装とツリーベースの実装を選択できます。これは、目的に適している場合と適していない場合があります(ほとんどの場合、ハッシュベースの実装が最適です。 、順序が重要な場合は、ツリーがニーズに適している可能性があります- HashSet vs TreeSet(ここStackoverflow) )も参照してください。

Treeを特別な種類のGraph(それは)であると考えている場合、一般的なコレクション(本質的にはリストであり、順番に使用される)ではなく、グラフに適用される特定のプロパティに関心がありますグラフなどを実装します)。

このスレッドで述べたように、グラフのモデリングに興味がある場合、グラフライブラリには多くの選択肢があります。個人的には JGraphT をお勧めします。

わからないなぜJDK内にグラフライブラリがないのか(そして、それが質問するのが良いかどうかわからない)、しかしSunは去ることを決めたと思うグラフを必要とするほとんどのアプリケーションは非常にユニークな実装も必要とするため、これは開発者にとって重要です。

12
scravy

答えは、次の2つのことの組み合わせであると思われます。

  • 一般的なツリーまたはグラフインターフェイスは「機能が不十分」です。
  • フィールドを使用して子および(必要な場合は)親ポインターを表すツリーまたはグラフを実装する方が簡単で効率的です。

Apache commonsもGoogle commonsも、一般的なグラフまたはツリーをサポートしていないことに注意してください。しかし、私はいくつかの一般的なツリー/グラフ階層に出くわしました:

  • JavaNetのjsfcompoundsプロジェクトには、 "com.truchsess.util" グラフおよびツリーフレームワークがあります。
  • SourceForgeの OpenJGraph プロジェクト(非アクティブ)には、ツリーライブラリとグラフライブラリが含まれています。
6
Stephen C

元の回答

グラフ(および、より具体的には、ツリーは1つだけのルートがあり、ループがなく、すべてのノードが接続される特別なケース)の主な問題は、その想定されるコレクションの各アイテムが別の構造に保持されることです:ノード。 「コンテナ」の二重層を必要とするため、この種の処理を標準化するのは難しい。

誰かがTreeModelJTreeを使用した場合、TreeNodesが背後にある(内部にある)ことを避けることはほとんど不可能であることに気付くでしょう。ノードとツリーの両方。

とにかく、私は構造が有用であることに同意しますが、それを標準にすることは非常に難しいです、例えば、Apache Commons Collections google Guavaも、API用の2つの大きなコレクション拡張機能もありません。

更新

APIの概要 によると:

主な設計目標は、サイズが小さく、さらに重要なことには「概念的な重み」がかなり小さいAPIを作成することでした。新しい機能が現在のJavaプログラマーにとって異質ではないように思われることが重要でした。それらを置き換えるのではなく、現在の機能を増強しなければなりませんでした。上記のすべての利点を提供します。

したがって、グラフ 適切なコレクション であり、標準化することは可能かもしれませんが、実装のサイズと複雑さは、前述の必要性のために、この設計目標に適合するには大きすぎますコンテナの二重層。

また、Google Guava グラフのサポートが追加されました 。 Apache グラフ用のサンドボックス(開発中)がありました が、2011年以降休止しているようです。

3

答えは次のとおりです。一般的なツリー構造とインターフェイスの設計と保守は面倒です( この投稿 の回答を参照)。ほとんどのユーザーは、リストとセットのツリーベースの実装のパフォーマンスが必要になりますが、内部には関心がないため、それらのほとんどは隠されています。

2
rodion

ツリー用のインターフェースがあります-javax.swing.tree.TreeModel、これは実際には任意の有向グラフ(顕著な「ルート」ノード)で機能します。ただし、Collectionインターフェースは実装していません(Swingはコレクションフレームワークよりも少し古いため、ここでコレクションであることが本当に適切かどうかは明確ではありません)。 (TreeModelの実装の1つはDefaultTreeModelであり、TreeNodeオブジェクトからツリービルドを使用します。このオブジェクト自体はユーザーが実装できるインターフェイスです。)

別のタイプのツリーは、XML-DOMフレームワークによって提供されます。いくつかの特定の使用ツリー(または主に「ツリーノード」)は、Java.io.FileJava.awt.Component(およびサブクラス)、コンパイラツリーAPI(com.Sun.source.tree.*)、ドックレットAPI(com.Sun.javadoc.*)、Reflection API(Java.lang.Class)、言語モデルAPI(javax.lang.**)。

これらのAPIを比較する場合

問題は、ツリーのための明確な汎用の便利なインターフェースがないことです-そのようなツリーは何ができるはずですか?ツリーは単に他のツリーのコレクション(1レベル下)ですか、それとも各ノード自体がより多くのノードを含むルートノードへのポインタですか?または、ツリーはすべてのノードのコレクションですか?または、すべてのノードのすべてのコンテンツのコレクションですか?すべてのノードに「コンテンツ」、またはリーフノードのみが必要ですか?ツリーが(ノード自体ではなく)いくつかのコンテンツ要素のコレクションである場合、イテレーターはどのように動作する必要がありますか?木のサイズはどれくらいですか?

以下に、ツリーノード(または、実際には、親ポインター用でない場合は一般的な有向グラフノード)インターフェイスの提案を示します。

/**
 * A general interface for a tree node.
 * @param <N> the concrete node type.
 */
public interface Node<N extends Node<N>> {

   /**
    * equivalent to {@link #children children()}.{@link Collection#isEmpty isEmpty()}.
    * @returns true, if this is a leaf node, else false.
    */
   public boolean isLeaf();

   /**
    * returns a collection of all children of this node.
    * This collection can be changed, if this node is mutable.
    */
   public Collection<N> children();
   /**
    * returns the parent of this node.
    * @return null, if this is the root node, or the node does not know its parent, or has multiple parents.
    */
   public N parent();
}

/**
 * a tree node with content objects.
 * @param <N> the concrete node type
 * @param <C> the type of the content of this node.
 */
public interface ContentNode<C,N extends ContentNode<C,N>>
          extends Node<N>
{
   /**
    * returns the content of this node, if any.
    */
   public C content();
}

上記のように、これはすべてのタイプのツリーに十分でしょうか?そうは思いません。

1
Paŭlo Ebermann