it-swarm.com.de

Wie definiere ich eine Methode, die ein Lambda als Parameter in Java 8 verwendet?

In Java 8 können Methoden als Lambda-Ausdrücke erstellt und als Referenz übergeben werden (mit ein wenig Arbeit unter der Haube). Es gibt viele Beispiele online, bei denen Lambda-Werte erstellt und mit Methoden verwendet werden. Es gibt jedoch keine Beispiele dafür, wie eine Methode erstellt wird, bei der Lambda als Parameter verwendet wird. Was ist die Syntax dafür?

MyClass.method((a, b) -> a+b);


class MyClass{
  //How do I define this method?
  static int method(Lambda l){
    return l(5, 10);
  }
}
312
Marius

Lambdas sind reine Call-Site-Konstrukte: Der Empfänger des Lambda muss nicht wissen, dass es sich um ein Lambda handelt, sondern akzeptiert ein Interface mit der entsprechenden Methode.

Mit anderen Worten, Sie definieren oder verwenden eine funktionale Schnittstelle (d. H. Eine Schnittstelle mit einer einzigen Methode), die genau das akzeptiert und zurückgibt, was Sie möchten.

Zu diesem Zweck enthält Java 8 eine Reihe häufig verwendeter Schnittstellentypen in Java.util.function (Dank an Maurice Naftalin für den Hinweis auf die JavaDoc).

Für diesen speziellen Anwendungsfall gibt es Java.util.function.IntBinaryOperator mit eine einzelne int applyAsInt(int left, int right) -Methode , sodass Sie Ihr method folgendermaßen schreiben können:

_static int method(IntBinaryOperator op){
    return op.applyAsInt(5, 10);
}
_

Sie können aber genauso gut Ihr eigenes Interface definieren und wie folgt verwenden:

_public interface TwoArgIntOperator {
    public int op(int a, int b);
}

//elsewhere:
static int method(TwoArgIntOperator operator) {
    return operator.op(5, 10);
}
_

Die Verwendung einer eigenen Benutzeroberfläche hat den Vorteil, dass Sie Namen haben können, die die Absicht deutlicher angeben.

215
Joachim Sauer

Um den Lambda-Ausdruck zu verwenden, müssen Sie entweder eine eigene Funktionsschnittstelle erstellen oder die Funktionsschnittstelle Java für Operationen verwenden, für die zwei Ganzzahlen erforderlich sind und die als Wert zurückgegeben werden. IntBinaryOperator

Benutzerdefinierte Funktionsschnittstelle verwenden

interface TwoArgInterface {

    public int operation(int a, int b);
}

public class MyClass {

    public static void main(String javalatte[]) {
        // this is lambda expression
        TwoArgInterface plusOperation = (a, b) -> a + b;
        System.out.println("Sum of 10,34 : " + plusOperation.operation(10, 34));

    }
}

Java Funktionsschnittstelle verwenden

import Java.util.function.IntBinaryOperator;

public class MyClass1 {

    static void main(String javalatte[]) {
        // this is lambda expression
        IntBinaryOperator plusOperation = (a, b) -> a + b;
        System.out.println("Sum of 10,34 : " + plusOperation.applyAsInt(10, 34));

    }
}

Ein anderes Beispiel, das ich erstellt habe, ist hier

58
pardeep131085

Für Funktionen, die nicht mehr als 2 Parameter haben, können Sie diese übergeben, ohne eine eigene Schnittstelle zu definieren. Zum Beispiel

_class Klass {
  static List<String> foo(Integer a, String b) { ... }
}

class MyClass{

  static List<String> method(BiFunction<Integer, String, List<String>> fn){
    return fn.apply(5, "FooBar");
  }
}

List<String> lStr = MyClass.method((a, b) -> Klass.foo((Integer) a, (String) b));
_

In BiFunction<Integer, String, List<String>> sind Integer und String seine Parameter, und _List<String>_ ist sein Rückgabetyp.

Für eine Funktion mit nur einem Parameter können Sie Function<T, R> verwenden, wobei T ist sein Parametertyp und R ist sein Rückgabewerttyp. Lesen Sie diese Seite für alle Schnittstellen, die bereits von Java zur Verfügung gestellt werden.

35
David Wu

Es gibt eine öffentlich zugängliche Version der Lambda-fähigen Java 8 JavaDocs, die von http://lambdafaq.org/lambda-resources verlinkt sind. (Dies sollte natürlich ein Kommentar zu Joachim Sauers Antwort sein, aber ich kann nicht in mein SO Konto mit den Reputationspunkten gelangen, die ich zum Hinzufügen eines Kommentars benötige.) Die Lambdafaq-Site (ich pflege sie) antwortet darauf und viele andere Java-Lambda-Fragen.

NB Diese Antwort wurde geschrieben, bevor die Java 8 GA -Dokumentation öffentlich verfügbar wurde. Ich habe es jedoch nicht geändert, da die Lambda-FAQ für Leute, die etwas über die in Java 8 eingeführten Funktionen lernen möchten, immer noch hilfreich sein könnte.

14

Für jeden, der dies googelt, wäre die Verwendung von Java.util.function.BiConsumer eine gute Methode. Ex:

Import Java.util.function.Consumer
public Class Main {
    public static void runLambda(BiConsumer<Integer, Integer> lambda) {
        lambda.accept(102, 54)
    }

    public static void main(String[] args) {
        runLambda((int1, int2) -> System.out.println(int1 + " + " + int2 + " = " + (int1 + int2)));
    }

Der Ausdruck wäre: 166

6
Big_Bad_E

Für mich ist die sinnvollste Lösung, eine Callback Schnittstelle zu definieren:

interface Callback {
    void call();
}

und dann, um es als Parameter in der Funktion zu verwenden, die Sie aufrufen möchten:

void somewhereInYourCode() {
    method(() -> {
        // You've passed a lambda!
        // method() is done, do whatever you want here.
    });
}

void method(Callback callback) {
    // Do what you have to do
    // ...

    // Don't forget to notify the caller once you're done
    callback.call();
}

Nur eine Präzision

Ein Lambda ist keine spezielle Schnittstelle, Klasse oder etwas anderes, das Sie selbst deklarieren könnten. Lambda ist nur der Name der speziellen Syntax () -> {}, die eine bessere Lesbarkeit bei der Übergabe von Einzelmethodenschnittstellen als Parameter ermöglicht. Es wurde entwickelt, um dies zu ersetzen:

method(new Callback() {
    @Override
    public void call() {
        // Classic interface implementation, lot of useless boilerplate code.
        // method() is done, do whatever you want here.
    }
});

Im obigen Beispiel ist Callbacknicht ein Lambda, es ist nur eine reguläre Schnittstelle. lambda ist der Name der Verknüpfungssyntax, mit der Sie sie implementieren können.

4
flawyte

Lambda-Ausdruck kann als Argument übergeben werden. Um einen Lambda-Ausdruck als Argument zu übergeben, muss der Typ des Parameters (der den Lambda-Ausdruck als Argument empfängt) vom Typ einer funktionalen Schnittstelle sein.

Wenn es eine funktionierende Schnittstelle gibt -

interface IMyFunc {
   boolean test(int num);
}

Und es gibt eine Filtermethode, die das int nur dann in die Liste einfügt, wenn es größer als 5 ist. Beachten Sie hier, dass die Filtermethode die Funktionsschnittstelle IMyFunc als einen der Parameter hat. In diesem Fall kann der Lambda-Ausdruck als Argument für den Methodenparameter übergeben werden.

public class LambdaDemo {
    public static List<Integer> filter(IMyFunc testNum, List<Integer> listItems) {
        List<Integer> result = new ArrayList<Integer>();
        for(Integer item: listItems) {
            if(testNum.test(item)) {
                result.add(item);
            }
        }
        return result;
    }
    public static void main(String[] args) {
        List<Integer> myList = new ArrayList<Integer>();
        myList.add(1);
        myList.add(4);
        myList.add(6);
        myList.add(7);
        // calling filter method with a lambda expression
        // as one of the param
        Collection<Integer> values = filter(n -> n > 5, myList);

        System.out.println("Filtered values " + values);
    }
}
4
infoj

Um einen Lamda-Ausdruck als Parameter zu übergeben, benötigen wir einen Typ, in dem wir ihn halten können. Genau wie ein ganzzahliger Wert halten wir in der primitiven Klasse int oder Integer. Java hat keinen separaten Typ für den Lamda-Ausdruck, sondern verwendet eine Schnittstelle als Typ für das Argument. Diese Schnittstelle sollte aber eine funktionale Schnittstelle sein.

1
Vamshi

Lambda ist kein Objekt, sondern eine funktionale Schnittstelle. Es können so viele Funktionsschnittstellen definiert werden, wie das @FuntionalInterface als Annotation verwendet werden kann

@FuntionalInterface
public interface SumLambdaExpression {
     public int do(int a, int b);
}

public class MyClass {
     public static void main(String [] args) {
          SumLambdaExpression s = (a,b)->a+b;
          lambdaArgFunction(s);
     }

     public static void lambdaArgFunction(SumLambdaExpression s) {
          System.out.println("Output : "+s.do(2,5));
     }
}

Die Ausgabe wird wie folgt sein

Output : 7

Das Grundkonzept eines Lambda-Ausdrucks besteht darin, eine eigene Logik zu definieren, aber bereits definierte Argumente. Im obigen Code können Sie also die Definition der Funktion do von einer anderen Definition zu einer anderen hinzufügen, aber Ihre Argumente sind auf 2 beschränkt.

1
raja emani

Das ist ganz einfach. Der Zweck des Lambda-Ausdrucks ist die Implementierung der funktionalen Schnittstelle. Es ist die Schnittstelle mit nur einer Methode. Hier ist ein großartiger Artikel über vordefinierte und ältere funktionale Schnittstellen.

Wie auch immer, wenn Sie Ihre eigene funktionale Schnittstelle implementieren möchten, machen Sie es. Nur zum einfachen Beispiel:

public interface MyFunctionalInterface {
    String makeIt(String s);
}

Erstellen wir also eine Klasse, in der wir eine Methode erstellen, die den Typ MyFunctionalInterface akzeptiert:

public class Main {

    static void printIt(String s, MyFunctionalInterface f) {
        System.out.println(f.makeIt(s));
    }

    public static void main(String[] args) {

    }
}

Als letztes müssen Sie die Implementierung des MyFunctionalInterface an die von uns definierte Methode übergeben:

public class Main {

    static void printIt(String s, MyFunctionalInterface f) {
        System.out.println(f.makeIt(s));
    }

    public static void main(String[] args) {
        printIt("Java", s -> s + " is Awesome");
    }
}

Das ist es!

1
SanchelliosProg

Mach Folgendes ..

Sie haben method(lambda l) deklariert. Sie möchten lediglich ein Interface mit dem Namen lambda erstellen und eine abstrakte Methode deklarieren

public int add(int a,int b);  

methodenname spielt hier keine Rolle ..

Wenn Sie also MyClass.method( (a,b)->a+b) aufrufen, wird diese Implementierung (a,b)->a+b in Ihre Methode zum Hinzufügen von Schnittstellen eingefügt. Wenn Sie l.add aufrufen, wird diese Implementierung verwendet und das Hinzufügen von a ausgeführt. und b und return l.add(2,3) geben 5 zurück. - Im Grunde ist das, was Lambda tut ..

0
Arasn