Java8のStream APIの一部処理への委譲がCollection側に実装されていないのはなぜでしょう?
解決済
回答 4
投稿 ・編集
- 評価
- クリップ 0
- VIEW 2,325
たとえば、Java8でリストにフィルタをかける場合には以下のような記述をすると思います。
List<String> list = Arrays.asList("Galileo", "Helios", "Indigo", "Juno", "Kepler", "Luna");
List<String> filterList = list.stream()
.filter(s -> s.contains("a"))
.collect(Collectors.toList());
groupByコレクターのような戻り方のコレクション自体が変わるパターンは難しいとは思いますが、
filterやmapなどの中間処理メソッドはCollectionインタフェースにそのまま定義されていれば、
List<String> filterList = list.filter(s -> s.contains("a"));
のようにコードがもう少し短くなるのになぁと思ってしまいます。
インタフェースへのデフォルト実装も導入されたことですし、
処理委譲があってもいいのにと思うのですが、なにか問題があったりするのでしょうか?
ちなみに、Streamはプリミティブも扱えるのが素敵ですよね。
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
List<String> filterList = list.filter(s -> s.contains("a"));
のようにコードがもう少し短くなるのになぁと思ってしまいます。
List
というのは中身の数が決まった箱です。一方Stream
はそうではありません。
例えば中身が100万あるListを
list.map(...).filter(...).map(...)
のように書くと
100万のサイズを持つ箱が何回も作り直されてしまい、これはパフォーマンス上の問題になります。
初心者がうっかりそうしないように、Listは直接 filter というメソッドを持たないのだと思います。
Javaに似た言語 C# では、Listから直接
filter
と同様のメソッドWhere
を呼び出すことができますが、戻り値はListではありません。
IList<int> numbers = getNumbers();
IEnumerable<int> evens = numbers.Where(x => x % 2 == 0); // IEnumerableはJavaのStream相当
IList<int> evenList = numbers.Where(x => x % 2 == 0).ToList(); // Listを作り直す
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
filterなどのインターフェースはStreamとしてのものでListのものではないということだと思います。もしListがStreamとして扱ってよい類のものなら別ですが役割はやはり別ではないでしょうか?Streamは文字通りデータの流れを扱うものであってListはデータを保持する役割と感じます。
filterが最初からあると確かに便利と感じますが、ではストリームの他のメソッドはなくてもいいのかと考えると...便利そうだからということで無秩序に機能を追加するのはListというもののインターフェースを壊してしまう危険があるように思います。それよりもstream()のみ追加してそれを解してストリームの全機能を使えるとした方があるべき姿ということなのかも知れません。
ちなみにListにfilterというメソッドがあったとすると自分なら「Listの全要素からprecicateにより選択した要素だけを持つListを返す」というメソッドをイメージします。結果がStreamですといわれるとなんでそんな機能がListにあるの?と思ってしまうような気がします。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
+1
それができたとしても元のコレクションの方と同じ型を得るには、キャストするしかなさそうです。
手前味噌で恐縮ですが...私も以前、同様のことを考えて、こういう記事を書きました。
架空の拡張-filter,mapをStreamを使わずに組み込むとしたら - argius note
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
0
悩みましたがhello-worldさんの解答が一番なるほどと思ったためベストアンサーとさせていただきます。
確かに複数回の中間処理をするたびにコレクションを作り直すのは微妙ですね。
とはいってもJava7までであれば普通にやっている気もしますが…。
たとえばListインタフェースに以下のようなメソッドを書いたらダメか?
というようなイメージでした。
default List<E> filter(Predicate<? super E> predicate) {
return this.stream().filter(predicate).collect(Collectors.toList());
}
default <R> List<R> map(Function<? super E, ? extends R> mapper) {
return this.stream().map(mapper).collect(Collectors.toList());
}
argiusさんの記事を読ませていただきましたが、とても参考になりました。
そしてただの処理委譲をしようとしていたずぼらな私よりも
より高度な考察をなさっていてなるほどなぁと思うことしきりです。
インスタンスの生成型というのは盲点で、Collectors#toListの実装を眺めてみたりしましたが、
これってArrayList固定になっていて、それ以外を使う場合にはファクトリを渡すのですね。
あまり考えたこともありませんでした。
とても良い考察ができたことに感謝いたします。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.21%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる