APIにより、コレクションの関数型ライクな操作ができるようになりました。mapのような処理が1行で書けるようになってうれしい反面、もうちょっとすっきりしたのが良かったな、という不満もあります。不満を言っているだけの人になるのも嫌なので、「もし、こういう風に実装したならば、あるいは」というのを考えてみました。Java8でStreamでfilterとmapを使う既存のコードとの兼ね合いを考えると、入力も出力もList<String>の場合が多いと思うので、その前提で。input.stream().map(String::toUpperCase).collect(Collectors.toList());1行で書けるのはうれしいんですけど、1つのfilter/mapを使うために余分に3つものメソッド呼び出しを書かなければなりません。Listにfilter/mapをつけてくれたら良かったのに、と思いました。関数型ライブラリーを使えば良いんじゃないの?FunctionalJavaのような、可能な限りの関数型の表現を実現しようとするライブラリーがありますが、これは新たなクラス体系を作っています。できれば、コアライブラリーのJCFをそのまま使って実現したいし、あと、関数型のレイヤーが厚すぎて拡張されたJavaになってしまうのは避けたい。関数型じゃなくて、あくまで、コア機能に直接組み込んでもそれほど違和感が無い程度のfilter/mapだけで良いんです。Listのfilter/mapだけで良いから、欲しい。標準ライブラリーに組み込むとしたらjava.util.ListとStreamの上位に、Sequenceのようなインターフェイスがあると綺麗になりそうですが。Sequenceを導入したら、Sequenceには実装をほとんど書かないで、NonLazySequenceにdefaultメソッドを書く、といった感じでしょうか。Sequence(実在しない)StreamNonLazySequence(実在しない)List上の方法だと実験が大掛かりになってしまうので、java.util.Listだけに実装するようにして、極力、java.util.List以外を触らなくて良いように、defaultメソッドかstaticメソッドを追加するだけで拡張できる方法を考えてみました。以下のインターフェイスは、Listに継承させる前提で書いています。実際はListに直接追加しても良いかと思いますが、ここではコードを分割するためにも別のインターフェイスとしています。架空のコードなので、実在のクラス名にはYaという接頭辞を付けています。}}まず、filter/mapを実現するには、元のコレクションを複製する手段が必要になります。元のコレクションのすべての要素を並び順にイテレートできる元のコレクションと同じ型、もしくは互換性のある型のインスタンスを新たに生成する新たに生成したインスタンスに値を追加できるの操作ができるようになっていなければなりません。最初のイテレートは、Iterableを実装することで対応できます。Listの上位インターフェイスであるCollectionでもIterableを実装しているので、直接Listにコードを追加するなら不要です。インスタンスの生成は、デフォルトではArrayList固定で。コンストラクター参照を使います。コンストラクターを指定したい場合は、引数が3のメソッドで、2番目にコンストラクター参照(たとえばLinkedList::new)を渡します。オーバーライドは必須ではありませんが、可能であればサブクラス自体のインスタンスを返すのが相応しいと思われます。値を追加するのは、addメソッドで。これも、Collectionのものなので、直接Listにコードを追加するなら不要です。あとは、filter/mapを書くだけ。メソッド名がfilteredList/mappedListなのは、Javaでは継承階層の途中で自分自身の型を戻り値の型にすることができない*1ので、Sequenceがあった場合に名前がかぶってしまうのを避けるためです。ちなみにScalaだと、オーバーライドしたメソッドの戻り値を変えることができるのでそれが可能になっています。(scala.collection.TraversableLike、scala.collection.SeqLikeあたりを参照。)実際にできる方法でできないことばかりを言うのはこのくらいにして、現実的な解法を考えましょう。ユーティリティーメソッドクラスを作ってしまうのが手っ取り早いでしょうか。}}ここでは、filterMapと、配列向けのオーバーロードメソッドも作ってみました。x.length());あまりスマートとは言えないやり方ですが、少なくとも私にとっては、配列かListでfilter/mapができれば事足りるので、これで十分です。おわりになんにせよ、ラムダ式とインターフェイスのデフォルトメソッド(static含む)が使えるようになったのは大きいですね。*1:分かりやすく説明するのが難しい。継承関係が親子1世代しかない場合ならできます。(2)プロフィールid:argiusはてなブログをはじめよう!argiusさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。