wrongwrongな開発日記

しんまいさんの忘備録

【Java】Functionを使ってみる

タイトル通り、Java 8で追加されたFunctionが便利だったので書きます。

関数型インターフェース関連でとても参考になるページ

Java関数型インターフェースメモ(Hishidama's Java8 Functional Interface Memo)

Functionとは

Function<T,R> は引数Tを受け取って戻り値Rを返す関数を変数っぽく扱えるものです。大体cの関数ポインタとか.Netのdelegateみたいなもんです。
例えば以下の例では、funcintを受け取って処理を行い、intを返します。

Function<Integer, Integer> func = input -> input * 3; //int inputに3を掛けたものが帰る
func.apply(3); //呼び出し例、3 * 3 = 9が帰る

正直うまく書けて無いと思うので、以下の記事を参照してください。。。
www.atmarkit.co.jp

なにがうれしい?

同じxを入力とする一次関数と二次関数があり、それぞれパラメータはある程度一定であるような場合を例に書きます。結論のソースコード全体は一番下に置きます。

素直に書くと

素直に書くと以下のようになります。
変化するのはxだけなのに何度も何度も変数を書いて関数を呼び出して……というのは一々書くのがダサくて面倒くさいです。各関数のパラメータも、何らかのラベル付けをした方がTypoによる事故も起きにくいと思われます。

private static int linearFunction(int a, int b, int x){
    return a * x + b;
}
private static int quadricFunction(int a, int p, int q, int x){
    return a * (x - p) + q;
}
public static void main(String[] args) {
    int x = 2;
    System.out.println(linearFunction(1, 1, x));
    System.out.println(quadricFunction(1, 1, 1, x));
}
Function + EnumMap

これをFunction + EnumMapで書き直すと以下のようになります。
Enumでラベルを付けてマップに登録して呼び出してます。呼び出しがスッキリしたのとかはうれしいです。もうちょっといいやり方が有る気もしますがとりあえず気にしないことにします。

private enum e{
    La1b2,
    Qa1p1q1,
}

private static int linearFunction(int a, int b, int x){
    return a * x + b;
}
private static int quadricFunction(int a, int p, int q, int x){
    return a * (x - p) + q;
}

private static final EnumMap<e, Function<Integer, Integer>> map;
static {
    map = new EnumMap<>(e.class);
    map.put(e.La1b2, x -> linearFunction(1, 2, x));
    map.put(e.Qa1p1q1, x -> quadricFunction(1, 1, 1, x));
}

public static void main(String[] args) {
    System.out.println(map.get(e.La1b2).apply(2));
    System.out.println(map.get(e.Qa1p1q1).apply(2));
}

ソースコード全体

import java.util.EnumMap;
import java.util.function.Function;

public class Main {
    private enum e{
        La1b2,
        Qa1p1q1,
    }

    private static int linearFunction(int a, int b, int x){
        return a * x + b;
    }
    private static int quadricFunction(int a, int p, int q, int x){
        return a * (x - p) + q;
    }

    private static final EnumMap<e, Function<Integer, Integer>> map;
    static {
        map = new EnumMap<>(e.class);
        map.put(e.La1b2, x -> linearFunction(1, 2, x));
        map.put(e.Qa1p1q1, x -> quadricFunction(1, 1, 1, x));
    }

    private static Function<Integer, Integer> func = input -> input * 3;

    public static void main(String[] args) {
        System.out.println(map.get(e.La1b2).apply(2));
        System.out.println(map.get(e.Qa1p1q1).apply(2));
    }
}