498 Stimmen

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

In Java 8 können Methoden als Lambda-Ausdrücke erstellt und per Referenz übergeben werden (mit ein wenig Arbeit unter der Haube). Es gibt viele Beispiele im Internet, in denen Lambdas erstellt und mit Methoden verwendet werden, aber keine Beispiele dafür, wie man eine Methode erstellt, die ein Lambda als Parameter annimmt. Wie lautet 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);
  }
}

329voto

Joachim Sauer Punkte 290477

Lambdas sind ein reines Call-Site-Konstrukt: Der Empfänger des Lambdas braucht nicht zu wissen, dass es sich um ein Lambda handelt, sondern akzeptiert eine Schnittstelle 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 annimmt und zurückgibt, was Sie wollen.

Seit Java 8 gibt es eine Reihe von häufig verwendeten Schnittstellentypen in java.util.function .

Für diesen speziellen Anwendungsfall gibt es java.util.function.IntBinaryOperator con eine einzige int applyAsInt(int left, int right) Methode schreiben, damit Sie Ihre method wie diese:

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

Sie können aber genauso gut Ihre eigene Schnittstelle definieren und sie so verwenden:

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

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

Dann rufen Sie die Methode mit einem Lambda als Parameter auf:

public static void main(String[] args) {
    TwoArgIntOperator addTwoInts = (a, b) -> a + b;
    int result = method(addTwoInts);
    System.out.println("Result: " + result);
}

Die Verwendung einer eigenen Schnittstelle hat den Vorteil, dass Sie Namen verwenden können, die die Absicht deutlicher machen.

76voto

pardeep131085 Punkte 5380

Um Lambda-Ausdrücke zu verwenden, müssen Sie entweder Ihre eigene funktionale Schnittstelle erstellen oder die funktionale Schnittstelle von Java für Operationen verwenden, die zwei Ganzzahlen und eine Rückgabe als Wert erfordern. IntBinaryOperator

Verwendung einer benutzerdefinierten funktionalen Schnittstelle

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));

    }
}

Verwendung der funktionalen Java-Schnittstelle

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));

    }
}

51voto

David Wu Punkte 580

Bei Funktionen, die nicht mehr als 2 Parameter haben, können Sie diese übergeben, ohne Ihre 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));

Unter BiFunction<Integer, String, List<String>> , Integer y String sind seine Parameter, und List<String> ist sein Rückgabetyp.

Für eine Funktion mit nur einem Parameter können Sie Function<T, R> , wobei T ist sein Parametertyp, und R ist der Typ des Rückgabewerts. Siehe hierzu Seite für alle Schnittstellen, die bereits von Java zur Verfügung gestellt werden.

27voto

Mickäel A. Punkte 8434

Meiner Meinung nach ist die sinnvollste Lösung die Definition einer Callback Schnittstelle :

interface Callback {
    void call();
}

und dann als Parameter in der aufzurufenden Funktion zu verwenden:

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();
}

Allerdings nur eine Präzision

Ein Lambda ist keine spezielle Schnittstelle, Klasse oder etwas anderes, das Sie selbst deklarieren könnten. Lambda ist nur die Bezeichnung für die () -> {} spezielle Syntax, die eine bessere Lesbarkeit bei der Übergabe von Ein-Methoden-Schnittstellen als Parameter ermöglicht. Sie wurde entwickelt, um diese :

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 also, Callback es pas ein Lambda, es ist einfach eine normale Schnittstelle; lambda ist der Name der Shortcut-Syntax, die Sie zur Implementierung verwenden können.

17voto

Maurice Naftalin Punkte 10126

Es gibt eine öffentliche, über das Web zugängliche Version der Lambda-fähigen Java 8 JavaDocs, verlinkt von http://lambdafaq.org/lambda-resources . (Dies sollte offensichtlich ein Kommentar zu Joachim Sauers Antwort sein, aber ich komme nicht in mein SO-Konto mit den Reputationspunkten, die ich brauche, um einen Kommentar hinzuzufügen). Die Lambdafaq-Site (ich pflege sie) beantwortet diese und viele andere Java-Lambda-Fragen.

NB: Diese Antwort wurde geschrieben, bevor die Dokumentation zu Java 8 GA veröffentlicht wurde. öffentlich zugänglich . Ich habe sie jedoch an Ort und Stelle belassen, weil die Lambda-FAQ könnte für Personen, die sich mit den in Java 8 eingeführten Funktionen vertraut machen wollen, immer noch nützlich sein.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X