2012-12-28 1 views
6

私はコレクションのようなツリーを開発している問題を考えてみましょう。Javaでレイジーコレクション

私のコレクションの主な機能の一つは、すべて格納されているアイテムを一つずつトレースして、満たされている与えられた基準(怠惰なコレクション)まで、各項目について与えられた機能を呼び出すことです。

だから、この関数は、次のシグネチャを持つ必要があります

void Trace(function func, criteria crit) 
{ 
    item i = firstItem(); 
    while (i != endItem()) 
    { 
     i = nextItem(); 
     func(i); 
     if (crit(i)) 
      return; 
    } 
} 

C++内の関数ポインタはfunccritのために使用することができます。
C#で、yieldキーワードはまさにこの問題の解決策であると私は信じています。

Javaで同じことをどのようにすることができますか?

+1

ループにはバグがあります。最後の要素は処理されません。 whileループが入力されない長さ1のリストを考えてみましょう。 – Bohemian

+0

グッドポイント:) しかし、幸いにも、それは問題とあまり関係がありません:) – MBZ

答えて

1

メソッドを宣言するインターフェイスを作成し、そのインターフェイスを実装するオブジェクトへの参照を引数として必要とします。呼び出し元は、匿名の内部クラスを使用してオブジェクトを作成できます。 Javaでは

2

、あなたが該当する機能を実装したクラスのオブジェクトへの参照を渡す、またはその代わりコモンズコレクションを使用します。

  • 使用crit一部についてPredicate実装。
  • funcパーツのClosure実装を使用してください。たとえば、

:あなたがここに探しているもの

Closure c = new Closure() { 
    public void execute(Object obj) { 
     ... 
    } 
}; 

Predicate p = new Predicate() { 
    public boolean evaluate(Object obj) { 
     ... 
    } 
} 

Trace(c, p); 
+0

+1、そしてコアJavaを使いたい場合は、[Callable](http://docs.oracle.com/javase/ 7/docs/api/java/util/concurrent/Callable.html)は、値を返すことができるクロージャのようなもののための合理的な汎用インタフェースを提供します。 –

+0

@RyanStewart、私の問題は、呼び出し可能なのは、OPが望んでいたAPIを提供していないということです。 'call()'メソッドはパラメータを受け取りません。つまり、各繰り返しで 'Callable'実装の新しいインスタンスを作成する必要があります。 – Isaac

2

Strategyデザインパターンです。

このパターンの目標は、アルゴリズムの実装を戦略オブジェクトに抽象化することです。ここでアルゴリズムは、あなたが渡そうとしているfunccritの関数です。

したがって、TraceStrategyという名前のインターフェイスがあります。次に、このインタフェースの実装をコレクションに渡します。あなたのコードは、その後

void Trace(TraceStrategy traceStrategy) 
{ 
    item i = firstItem(); 
    while (i != endItem()) 
    { 
     i = nextItem(); 
     traceStrategy.func(i); 
     if (traceStrategy.crit(i)) 
      return; 
    } 
} 

interface TraceStrategy { 
    public boolean crit(item i); 

    public void func(item i); 
} 

ようになりますがitemに縛られていなかったように、あなたはおそらく、これは一般的なようにしたいと思います...しかし、あなたのアイデアを得ます。

+1

このアプローチの問題は、 'crit'と' func'の間に常にカップリングが存在することです。 '' func'の '' crit''と '' y''の可能性がある場合は 'TraceStrategy'の' x * y'の実装を作成するかもしれません...したがって、パラメータ化はIMOのやや良い方法です。 – Isaac

+0

@Isaac、優れた点。 'CritStrategy'と' FuncStrategy'オブジェクトをとり、それらの2つで構成される複合オブジェクトを返す 'TraceStrategyFactory'を作成することができます...しかし、これらの2つの関数を結合することについてのあなたのポイントは非常にです。 – Dancrumb

+0

はい。戦略パターンとパラメタリゼーションの組み合わせがOP全体のニーズに最も適していることに同意します。 – Isaac

1

あなたが技術のカップルを組み合わせることにより、Javaでうまくこのtrace機能の作業を行うことができます。

代わり funccritは、特定のインタフェースを実装するオブジェクトのインスタンスである必要があり、「関数ポインタ」、あなたのパラメータの
  • 。オブジェクトのこのインタフェースの関数を呼び出すことができますi。実際には、これは2つの異なるビスタパラメータを持つVistorパターンです。
  • また、ツリーをトラバースする方法も必要です。 Iteratorを実装することができます。これにより、構造全体をトラバースする良い方法が得られます。あるいは、traceを再帰的にすることもできます(ツリーの左右の枝で自分自身を呼び出します)。それでイテレータは必要ありません。

イテレータのバージョンは次のようになります。

public void trace(IFunction func, ICriteria crit) { 
    for (T i: this) { 
     func.call(i); 
     if (crit.test(i)) return; 
    } 
} 

ここTコレクションのアイテムタイプで、calltestそれぞれIFunctionICriteriaインタフェースで関数定義されています。

関連する問題