web-dev-qa-db-ja.com

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

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

I.e:単一の変数が機能する:

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

可変引数も機能します。

    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の関数パッケージを調べましたが、見つけることができませんでした。これは可能ですか?

128
Leo Ufimtsev

このような機能的インターフェースを複数の型パラメーターで定義すれば可能です。そのような内蔵型はありません。 (複数のパラメータを持つ限られたタイプがいくつかあります。)

@FunctionalInterface
interface Function<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 {
    Function<String, Integer, Double, Void, List<Float>, Character> func = (a, b, c, d, e) -> 'z';
}

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


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

142

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";
};
25
tbodt

この場合は、デフォルトのライブラリ(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 "";
    };
}}
21
ayurchuk

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

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

1
PetroCliff

もう1つの選択肢は、これがあなたの特定の問題に当てはまるかどうかわからないが、それが当てはまるかもしれないいくつかの問題に、Java.util.functionライブラリのUnaryOperatorを使うことです。ここでは、指定したのと同じ型が返されるので、すべての変数を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
mel3kings

ラムダを利用するには:3種類の操作があります。
1。パラメーターを受け入れる - > Consumer
2。テストパラメータの戻り値 - >述語
3。パラメータ操作と戻り値の操作 - >機能

Javaの関数型インタフェース最大2つのパラメータ:
単一パラメータインタフェース
消費者
述語
関数

2パラメータインタフェース
BiConsumer
BiPredicate
バイファンクション

つ以上の場合、あなたは以下のように機能的なインターフェースを作成しなければなりません(消費者タイプ):

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

OOTB解決策は、package kotlin.jvm.functionsFunction0Function1 ... Function2を定義するFunction22をインポートすることです。

例えば。、

import kotlin.jvm.functions.*;

public void testFunction() {
    Function3<Integer, Integer, Integer, Integer> f3 = (x, y, z) -> x + y + z;
    System.out.println(f3.invoke(1, 2, 3));
    Function4<Integer, Integer, Integer, Integer, Integer> f4 = (a, b, c, d) -> a + b + c + d;
    System.out.println(f4.invoke(1, 2, 3, 4));
}

scalaにも同様の機能があります。

0
Leon