2016-05-26 3 views
8

ストリームは1回しか使用できず、汎用ソリューションの複雑さはO(m*n)であるため、2つのストリームの交差点を取得するか、交差点が空であるかどうかを見つけることは一般的に不可能です。 。我々は、基礎となるサプライヤーの性質について何も知らない場合は、我々は最大1つのストリームと一つのコレクションで逃げることができストリームの交差が空でないかどうかを調べる

:まだ

<T> boolean intersects(final Stream<T> c1, final Collection<T> c2) { 
    return c1.filter(c2::contains).findAny().isPresent(); 
} 

、両方とも私たちのサプライヤーが注文を表す場合にはどのような同じコンパレータを使用してソートされたコレクション(最も単純なケースでは、2つのTreeSetComparableです)?この場合、解はの線形の複雑さ(または、より正確にはO(m*n)this答えを参照してください)を持ちます。

今の質問:上記リニア溶液をのみストリームAPI(。。すなわち、入力として2つのストリームを使用)を使用して実装することができますか?

+0

ストリーム内のデータが注文されている場合にリニアソリューションを実装できるかどうか尋ねていますか? –

+4

反復的な解とストリームは合わないので、できることはストリーム上で 'iterator()'を呼び出すことです。 – Holger

+0

@JimMischelはい、まさに – Bass

答えて

7

あなただけのSetに第二の流れを収集し、最初のストリームのいずれかの要素がこのセットに含まれているかどうかを尋ねることができます:c1のうちのセットを作る

<T> boolean intersects(final Stream<T> c1, final Stream<T> c2) { 
    return c1.anyMatch(c2.collect(Collectors.toSet())::contains); 
} 

は数に関して線形でありますその中の要素であり、containsは一定時間操作です。

+0

これは良い解決策であり、メモリフットプリントごとの制限が設定されていないため、疑問が生じます。それでも、元の反復解法(2つのイテレータのどちらかを進める)では、ストリームベースの反復処理の間に余分なメモリを必要としません。新しいコレクションを導入しないで、同じタスクを線形時間で解決することは可能ですか? – Bass

+3

@Bass短い答え:いいえ。長い答え:noooooo。ストリームをイテレータに変換するのではなく、基本的に。 –

+2

@Bassそしてイテレータを持つことの問題は、要素を簡単に「見る」ことができないということです。あなたは 'next()'でそれを消費する必要があるので、2つのイテレータのうちの1つを進めるだけではずっと難しくなります。 – Tunaki

関連する問題