ホーム › 関数型プログラミング › Func-03
Func-03: 関数合成(andThen / compose)
複数の関数をつなげて1つの処理パイプラインを作る「関数合成」を解説します。andThen() は「f の後に g」(左から右)、compose() は「g を先に適用してから f」(右から左)という順序の違いを理解することが重要です。 また、Predicate の and()/or()/negate() で複数の条件を組み合わせる方法も学びます。
andThen と compose の違い
2つのメソッドは「どの順序で関数を適用するか」が逆になっています。 混乱しやすい箇所なので、具体的な例で確認しましょう。
| メソッド | 適用順序 | 数式で表すと | イメージ |
|---|---|---|---|
f.andThen(g) | f を先に適用し、その結果に g を適用 | g(f(x)) | 左から右(直感的) |
f.compose(g) | g を先に適用し、その結果に f を適用 | f(g(x)) | 右から左(数学の合成関数と同じ) |
Predicate の論理演算メソッド
p1.and(p2): p1 かつ p2 — 両方が true のとき truep1.or(p2): p1 または p2 — どちらか一方が true のとき truep.negate(): p の否定 — true と false を反転
サンプルコード
Java 8 で Function.andThen() と compose() が導入されました。andThen() は「f の後に g を適用」、compose() は「f.compose(g) = f(g(x)) で g を先に適用」です。Predicate には and()/or()/negate() があり、複数の条件を組み合わせられます。
よくあるミス・注意点
⚠️ andThen と compose で適用順が逆になる
f.andThen(g) は「f の後に g」ですが、f.compose(g) は「g の後に f」です。 たとえば toUpper.andThen(trim) は「大文字化してからトリム」ですが、toUpper.compose(trim) は「トリムしてから大文字化」と逆になります。 迷ったときは andThen() だけを使い、左から右の順に書くほうがわかりやすいです。
⚠️ Consumer.andThen() は副作用の連結であり、値を変換しない
Consumer.andThen() は Function と同じく 「前の Consumer の後に次の Consumer を実行する」という意味ですが、 Consumer は値を返さないため、各 Consumer は同じ入力値を受け取ります。 Function の andThen のように「前の結果を次に渡す」という動作とは異なる点に注意しましょう。
テストする観点
f.andThen(g)とf.compose(g)で適用順が逆になること(同じ入力で異なる結果になるケースで確認)- 3段合成
f.andThen(g).andThen(h)が左から順に適用されること Predicate.negate()で true/false が正しく反転されること(境界値: 判定がちょうど境界のとき)Predicate.and()で片方だけ true のケース・両方 true のケース・両方 false のケースを網羅すること- バリデーションパイプラインで、正常なメール・空文字・@なし の各入力に対して期待通りの valid 値が返ること