2016-03-02 3 views
7

ストリームの次の要素を覗く方法はありますか?アイデアはオブジェクトのリストのストリームから2つの次のオブジェクトを比較する必要があります(いくつかの差分を滑らかにするために、ここでは重要ではありません)。ストリーム内の次の要素を確認する

autobahn.stream() 
      .limit(autobahn.size()-1) 
      .filter(car -> car.speed < autobahn.get(autobahn.indexOf(car)+1).speed) 
      .forEach(car -> car.honk()); 

があるかもしれないので、この解決策の主な-問題は、indexOf方法であって、

List<Car> autobahn = getCars(); 
for (int i = 0; i < autobahn.size()-1; i++) { 
    if(autobahn.get(i).speed>autobahn.get(i+1).speed) 
     autobahn.get(i).honk(); 
} 

これまでの流れは以下のようになりよう最善の方法を:古いforループとしてこれは次のようになります。オートバンの同じ車の2倍。よりよい解決策はhelperClassの

class BoxedCar { 

    Car content; 

    BoxedCar(Car content) { 
     this.content = content; 
    } 
    boolean setContent(Car content) { 
     double speed = this.content.speed; 
     this.content = content; 
     return content.speed > speed; 
    } 
} 

で次の(または前のもの)の要素(助けクラスで、これはさえ可能かもしれませんが、恐ろしい見えます)

BoxedCar boxedCar = new BoxedCar(autobahn.get(0)); 
autobahn.stream() 
      .skip(1) 
      .filter(car -> boxedCar.setContent(car)) 
      .forEach(car -> car.winTheRace()); 

を覗き見するためにいくつかの方法だろうStream<Car>を一種のStream<(Car,Car)>に転用するには、最初のストリームで何とか作成された2番目のストリームを使用します(これはひどく聞こえますが、ここではこれがどのように見えるかわかりません)。

ストリームでこれを行うには良い方法がありますか、for -loopに固執していますか?

+3

forループはまったくばかげていません。実際には、これはおそらくあなたがこれを書くことができるクリーンなコードです。あなたはいつもインデックス上でストリームを使うことができますが、それだけです。 – Tunaki

+0

@俊明私は言った、ストリームはばかげて見えるだろう、for-loopではない。これまでのところ、私は明白な理由のためにforループを堅持しています。ストリームでもこれを達成する素晴らしい可能性があるのであれば、私は思っています。編集、あなたが間違っている部分を理解することができます、私はそれを削除します。 – ctst

+0

ああ、私は誤って誤解しました。 – Tunaki

答えて

3

forループで固執するのは悪い考えではありません。 Stream APIは、このタイプの要件に対して設計されていません。より多くの洞察を得るためにthat answerを参照することができます。

ただし、ストリームAPIを使用してこれを行う簡単な方法は、ランダムアクセスがあると仮定して、リストのインデックスにStreamを使用することです。

IntStream.range(0, autobahn.size() - 1) 
     .filter(i -> autobahn.get(i).speed > autobahn.get(i+1).speed) 
     .forEach(i -> autobahn.get(i).honk()); 

これはループのforと非常に似ています。非標準pairMap操作は要素の隣接ペアをマッピングすることができますが使用される。ここ

StreamEx.of(autobahn) 
     .pairMap((car, nextCar) -> car.speed < nextCar.speed ? car : null) 
     .nonNull() 
     .forEach(Car::honk); 

:私の自由StreamExライブラリを使用して

IntStream.range(0, autobahn.size() - 1) 
     .filter(i -> autobahn.get(i).speed < autobahn.get(i + 1).speed) 
     .forEach(i -> autobahn.get(i).honk()); 
+2

'for'ループと似ていますが、並列処理が可能です。 –

+0

@ ErickG.Hagstromが述べたように、これはより良い性能を持つかもしれません。何とか私はちょうどこのエレガントでシンプルなソリューションを監督しました。またこのリンクには、この面に関する興味深い答えがいくつかあります。この答えが実際に私のユースケース(LinkedList)でより速いのかどうかはわかりませんが、私の質問には間違いありません。 – ctst

+1

@ctstもしあなたが 'LinkedList'を持っているなら、これは間違いなく良い答えです。 LinkedListにはランダムアクセスがないため、インデックスによるアクセスは悲惨です。その場合は、最初に 'ArrayList'に変換するか、forループとイテレータを使用する方が良いでしょう。 – Tunaki

0

代わりにループのIntStreamを使用してはどうでしょう単一の要素にこれは任意のストリームソース(ランダムアクセスインデックス付きリストだけでなく)で動作し、かなりうまく並列化できます。

1

関連する問題