1. ホーム
  2. java

[解決済み] Javaにおいて、ループに対するストリームの利点は何ですか?[クローズド]

2022-05-02 17:09:37

質問

面接でこの質問をされたのですが、ベストな回答ができたとは思えません。私は、並列検索ができることと、NULL値が何らかの手段で処理されることを述べたのですが、思い出せませんでした。今になって、私はOptionalについて考えていたことに気づきました。私はここで何を見逃しているのでしょうか?彼らはそれがより良い、またはより簡潔なコードであると主張していますが、私は同意するのかどうかわかりません。


簡潔に回答されていることを考えると、結局のところ、この質問はそれほど広範なものではなかったようです。


もし、面接でこの質問をするのであれば、そして明らかにそうであるならば、この質問を分解することは、答えを見つけることを難しくする以外にどんな目的があるのでしょうか?つまり、何を求めているのでしょうか?質問を分解して、すべてのサブクエスチョンに回答させることはできますが、その後、すべてのサブクエスチョンへのリンクを持つ親質問を作成します...かなり愚かだと思いますが。ついでに、あまり広くない質問の例も教えてください。この質問の一部だけを聞いて、それでも意味のある答えを得る方法を私は知らないのです。全く同じ質問を別の方法ですることは可能です。例えば、quot;ストリームはどんな目的を果たすのか、quot;for loopの代わりにいつストリームを使うのか、quot;for loopの代わりになぜわざわざストリームを使うのか、quot;これらはすべてまったく同じ質問ですが。

...それとも、誰かが本当に長い複数点の回答をしたから、広すぎると見なされるのでしょうか?正直なところ、知る人ぞ知る、事実上どんな質問でもそうすることができます。例えば、あなたがJVMの作者の一人であるなら、私たちのほとんどができないのに、一日中for loopについて話すことができるかもしれませんね。

質問を特定の問題に限定し、適切な回答を特定するのに十分な詳細さを持つように編集してください。一度に複数の明確な質問をすることは避けてください。この質問を明確にするために、質問の仕方のページを参照してください。

後述するように、適切な回答がなされていることから、回答があること、そしてその回答が十分に容易であることが証明されています。

どのように解決するのか?

面接の質問で、デメリットを聞かずに、メリットについて聞いているのは面白いですね、両方ありますから。

ストリームはより宣言的なスタイルです。 . あるいは、より 表現力 のスタイルになります。を記述するよりも、コードで意図を宣言する方が良いと思われるかもしれません。 いかに ということです。

 return people
     .filter( p -> p.age() < 19)
     .collect(toList());

...は、リストからマッチする要素をフィルタリングしていることを明確に示しています。

 List<Person> filtered = new ArrayList<>();
 for(Person p : people) {
     if(p.age() < 19) {
         filtered.add(p);
     }
 }
 return filtered;

Says "I'm doing a loop"。ループの目的はロジックの奥に埋もれている。

ストリームはしばしば テーザー . 同じ例を見ると、このようになります。Terserが常に良いとは限りませんが、もし、簡潔さと表現力を同時に発揮できるのであれば、それに越したことはありません。

ストリームは関数と強い親和性を持っている . Java 8 ではラムダと関数型インターフェイスが導入され、強力なテクニックのおもちゃ箱が開かれました。ストリームは、オブジェクトのシーケンスに関数を適用するための最も便利で自然な方法を提供します。

ストリームはミュータビリティの減少を促す . これは関数型プログラミングの側面と関連していて、ストリームを使って書くようなプログラムは、オブジェクトを変更しないようなプログラムになる傾向があるのです。

ストリームは緩やかな結合を促進する . ストリームを処理するコードは、ストリームのソースや最終的な終了メソッドを知る必要はないのです。

ストリームは非常に高度な動作を簡潔に表現することができる . 例えば

 stream.filter(myfilter).findFirst();

一見すると、ストリーム全体をフィルタリングして、最初の要素を返しているように見えるかもしれません。しかし、実際には findFirst() そのため、1つの項目が見つかると効率的に停止します。

ストリームは、将来の効率化の可能性を秘めている . 一部の人はベンチマークを行い、インメモリ List や配列は、同等のループより遅くなることがあります。これは、より多くのオブジェクトとオーバーヘッドが存在するためと思われます。

しかし、ストリームはスケールします。Javaに組み込まれている並列ストリーム操作のサポートと同様に、ストリームをAPIとして使用する分散Map-Reduce用のライブラリがいくつか存在します。

デメリットは?

パフォーマンス : A for 配列のループは、ヒープとCPUの使用量の両方において非常に軽量です。もし生のスピードとメモリの倹約を優先するならば、ストリームを使う方が悪いです。

親しみやすさ .世界には、多くの言語背景を持つ、経験豊富な手続き型プログラマがたくさんいて、彼らにとってループは馴染み深く、ストリームは目新しいものです。ある環境では、そのような人にとって馴染みのあるコードを書きたいと思うものです。

認知的オーバーヘッド . その宣言的な性質と、コードの下で起こっていることの抽象化の増加により、コードが実行にどのように関係しているかについての新しいメンタルモデルを構築する必要があるかもしれません。実際には、うまくいかないときや、パフォーマンスや微妙なバグを深く分析する必要があるときだけ、この作業を行う必要があります。ただ動くだけでいいのです。

デバッガ というのも、単純なループは、従来のデバッガーが扱う変数やコードの場所に非常に近いからです。