Javaラムダは複数のパラメーターを持つことができますか?


157

Javaでは、ラムダに複数の異なる型を受け入れることは可能ですか?

つまり、単一の変数が機能します。

    Function <Integer, Integer> adder = i -> i + 1;
    System.out.println (adder.apply (10));

Varargsも機能します。

    Function <Integer [], Integer> multiAdder = ints -> {
        int sum = 0;
        for (Integer i : ints) {
            sum += i;
        }
        return sum;
    };

    //.... 
    System.out.println ((multiAdder.apply (new Integer [] { 1, 2, 3, 4 })));

しかし、私は多くの異なるタイプの引数を受け入れることができる何かが欲しい、例えば:

    Function <String, Integer, Double, Person, String> myLambda = a , b, c, d->  {
    [DO STUFF]
    return "done stuff"
    };

主な用途は、便宜上、関数内に小さなインライン関数を含めることです。

私はグーグルを見回して、Javaの関数パッケージを調べましたが、見つかりませんでした。これは可能ですか?

回答:


178

複数の型パラメーターを使用して、このような機能インターフェースを定義することは可能です。そのような組み込みタイプはありません。(複数のパラメーターを持ついくつかの限定されたタイプがあります。)

@FunctionalInterface
interface Function6<One, Two, Three, Four, Five, Six> {
    public Six apply(One one, Two two, Three three, Four four, Five five);
}

public static void main(String[] args) throws Exception {
    Function6<String, Integer, Double, Void, List<Float>, Character> func = (a, b, c, d, e) -> 'z';
}

Function6ここで呼んだ。名前は自由に決められます。Javaライブラリーの既存の名前と衝突しないようにしてください。


それがあなたが求めていたものである場合、可変数の型パラメーターを定義する方法もありません。


Scalaのような一部の言語は、1、2、3、4、5、6などの型パラメーターを使用して、そのような組み込み型の数を定義しています。


58
あなたはいつもカリー化を使用することができますFunction<One, Function<Two, Function<Three, Function<Four, Function<Five, Six>>>>> func = a -> b -> c -> d -> e -> 'z';
ホルガー

@SotiriosDelimanolis:私はむしろ、異なる名前を選択するだろうFunctionとの衝突れjava.util.function.Function<T,R>ているが、初心者のための明確ではない場合があるが。
ニコラス

@ニコラスそれは合理的です。編集。
Sotirios Delimanolis

39

パラメータが2つある場合は、を使用できますBiFunction。さらに必要な場合は、次のように独自の関数インターフェイスを定義できます。

@FunctionalInterface
public interface FourParameterFunction<T, U, V, W, R> {
    public R apply(T t, U u, V v, W w);
}

複数のパラメータがある場合は、次のように引数リストを括弧で囲む必要があります。

FourParameterFunction<String, Integer, Double, Person, String> myLambda = (a, b, c, d) -> {
    // do something
    return "done something";
};

34

この場合、デフォルトライブラリ(Java 1.8)のインターフェースを使用できます。

java.util.function.BiConsumer
java.util.function.BiFunction

インターフェイスのデフォルトメソッドの小さな(最良ではない)例があります。

default BiFunction<File, String, String> getFolderFileReader() {
    return (directory, fileName) -> {
        try {
            return FileUtils.readFile(directory, fileName);
        } catch (IOException e) {
            LOG.error("Unable to read file {} in {}.", fileName, directory.getAbsolutePath(), e);
        }
        return "";
    };
}}

5
これらのインターフェースを使用して要件を満たす方法を説明するために質問を修正すると、Java8ファンからより多くの投票が得られます。
Martin Cowie 2016年

3
BiFunctionでは、引数が2つの関数のみを定義できます。問題は、任意の数の引数を持つ関数についてです
Dmitry Klochkov

8

ラムダを使用するには、次の3つのタイプの操作があり
ます。1.パラメータの受け入れ->コンシューマ
2.テストパラメータの戻りブール値->述語
3.パラメータの操作と戻り値->関数

2つのパラメーターまでのJava機能インターフェース:
単一パラメーターインターフェース
コンシューマー
述語
関数

2パラメーターインターフェース
BiConsumer
BiPredicate
BiFunction

2つ以上の場合、次のように機能インターフェイスを作成する必要があります(コンシューマータイプ):

@FunctionalInterface
public interface FiveParameterConsumer<T, U, V, W, X> {
    public void accept(T t, U u, V v, W w, X x);
}

1

別の方法として、これが特定の問題に当てはまるかどうかはわかりませんが、いくつかに当てはまる可能性がある場合はUnaryOperator、java.util.functionライブラリで使用します。ここでは、指定した同じ型を返すため、すべての変数を1つのクラスに入れ、それをパラメーターとして使用します。

public class FunctionsLibraryUse {

    public static void main(String[] args){
        UnaryOperator<People> personsBirthday = (p) ->{
            System.out.println("it's " + p.getName() + " birthday!");
            p.setAge(p.getAge() + 1);
            return p;
        };
        People mel = new People();
        mel.setName("mel");
        mel.setAge(27);
        mel = personsBirthday.apply(mel);
        System.out.println("he is now : " + mel.getAge());

    }
}
class People{
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

したがって、この場合Person、所有するクラスは多数のインスタンス変数を持つことができ、ラムダ式のパラメーターを変更する必要はありません。

興味のある方のために、java.util.functionライブラリの使用方法に関するメモを書きました:http : //sysdotoutdotprint.com/index.php/2017/04/28/java-util-function-library/


1

jOOLライブラリを使用することもできます-https ://github.com/jOOQ/jOOL

すでにパラメータ数の異なる関数インターフェースを用意しています。たとえば、あなたが使用することができますorg.jooq.lambda.function.Function3からなど、Function0までFunction16

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.