Как определить метод, который принимает lambda в качестве параметра в Java 8?

java lambda java-8

148201 просмотра

10 ответа

42179 Репутация автора

В Java 8 методы могут быть созданы как выражения лямбда и могут передаваться по ссылке (с небольшой работой под капотом). В Интернете есть множество примеров, когда lambdas создается и используется с методами, но нет примеров того, как сделать метод, беря лямбда в качестве параметра. Каков синтаксис для этого?

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


class MyClass{
  //How do I define this method?
  static int method(Lambda l){
    return l(5, 10);
  }
}
Автор: Marius Источник Размещён: 28.11.2012 12:06

Ответы (10)


189 плюса

231026 Репутация автора

Решение

Lambdas - это просто конструкция сайта вызова: получателю лямбды не нужно знать, что участвует Лямбда, вместо этого он принимает интерфейс с соответствующим методом.

Другими словами, вы определяете или используете функциональный интерфейс (т. Е. Интерфейс с одним методом), который принимает и возвращает именно то, что вы хотите.

Для этого Java 8 поставляется с набором часто используемых типов интерфейсов java.util.function(благодаря Maurice Naftalin для подсказки о JavaDoc).

Для этого конкретного случая использования есть java.util.function.IntBinaryOperatorс одного int applyAsInt(int left, int right)методом , так что вы можете написать свой , methodкак это:

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

Но вы можете точно определить свой собственный интерфейс и использовать его так:

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

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

Использование вашего собственного интерфейса имеет то преимущество, что вы можете иметь имена, которые более четко указывают на намерение.

Автор: Joachim Sauer Размещён: 28.11.2012 12:09

13 плюса

8343 Репутация автора

Существует общедоступная доступная в Интернете версия Java-документов Java 8 с поддержкой Lambda, связанная с http://lambdafaq.org/lambda-resources . (Очевидно, это комментарий к ответу Йоахима Зауера, но я не могу войти в мою учетную запись SO с точками репутации, которые мне нужны, чтобы добавить комментарий.) На сайте lambdafaq (я его поддерживаю) ответы на это и многие другие Java лямбда-вопросы.

NB Этот ответ был написан до того, как документация Java 8 GA стала общедоступной . Однако я остался на месте, потому что часто задаваемые вопросы Lambda могут быть полезны для людей, изучающих функции, представленные на Java 8.

Автор: Maurice Naftalin Размещён: 28.11.2012 12:59

51 плюса

4402 Репутация автора

Чтобы использовать выражение Lambda, вам нужно либо создать свой собственный функциональный интерфейс, либо использовать функциональный интерфейс Java для работы, для которого требуется два значения integer и return as value. IntBinaryOperator

Использование пользовательского функционального интерфейса

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

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

    }
}

Другой пример, который я создал, здесь

Автор: pardeep131085 Размещён: 19.03.2014 03:28

30 плюса

401 Репутация автора

Для функций, которые не имеют более двух параметров, вы можете передавать их, не определяя свой собственный интерфейс. Например,

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>>, Integerи Stringявляются его параметрами, и List<String>является его возвращаемым типом.

Для функции с одним параметром вы можете использовать Function<T, R>, где Tэто его тип параметра, и Rявляется типом возвращаемого значения. См. Эту страницу для всех интерфейсов, которые уже доступны Java.

Автор: David Wu Размещён: 27.05.2015 03:19

3 плюса

451 Репутация автора

Выражение Lambda может быть передано как аргумент. Чтобы передать лямбда-выражение в качестве аргумента, тип параметра (который принимает лямбда-выражение в качестве аргумента) должен иметь тип функционального интерфейса.

Если есть функциональный интерфейс -

interface IMyFunc {
   boolean test(int num);
}

И есть метод фильтра, который добавляет int в список, только если он больше 5. Обратите внимание, что метод фильтра имеет функциональный интерфейс IMyFunc как один из параметров. В этом случае выражение lambda может быть передано в качестве аргумента для параметра метода.

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);
    }
}
Автор: infoj Размещён: 11.08.2015 05:09

-2 плюса

1082 Репутация автора

Существует гибкость в использовании лямбда в качестве параметра. Это позволяет функциональное программирование в Java. Основной синтаксис

param -> method_body

Ниже приведен способ, который можно определить как метод, использующий функциональный интерфейс (лямбда) в качестве параметра. а. если вы хотите определить метод, объявленный внутри функционального интерфейса, скажем, функциональный интерфейс задается как аргумент / параметр для метода, вызванного изmain()

@FunctionalInterface
interface FInterface{
    int callMeLambda(String temp);
}


class ConcreteClass{

    void funcUsesAnonymousOrLambda(FInterface fi){
        System.out.println("===Executing method arg instantiated with Lambda==="));
    }

    public static void main(){
        // calls a method having FInterface as an argument.
        funcUsesAnonymousOrLambda(new FInterface() {

            int callMeLambda(String temp){ //define callMeLambda(){} here..
                return 0;
            }
        }
    }

/***********Can be replaced by Lambda below*********/
        funcUsesAnonymousOrLambda( (x) -> {
            return 0; //(1)
        }

    }

FInterface fi = (x) -> {return 0; };

funcUsesAnonymousOrLambda (р);

Здесь выше видно, как выражение лямбда может быть заменено интерфейсом.

Выше объясняется конкретное использование лямбда-выражения, есть больше. ref Java 8 лямбда внутри лямбда не может изменять переменную из внешней лямбда

Автор: hi.nitish Размещён: 13.03.2017 11:35

1 плюс

420 Репутация автора

Ну, это легко. Целью лямбда-выражения является реализация функционального интерфейса. Это интерфейс только с одним методом. Здесь вы найдете статью о предопределенных и устаревших функциональных интерфейсах.

В любом случае, если вы хотите реализовать свой собственный функциональный интерфейс, сделайте это. Просто для простого примера:

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

Итак, давайте сделаем класс, где мы создадим метод, который принимает тип MyFunctionalInterface :

public class Main {

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

    public static void main(String[] args) {

    }
}

Последнее, что вам нужно сделать, это передать реализацию MyFunctionalInterface методу, который мы определили:

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

Это оно!

Автор: SanchelliosProg Размещён: 20.04.2018 05:46

1 плюс

17 Репутация автора

Лямбда не объект, а функциональный интерфейс. Можно определить столько, сколько функциональных интерфейсов, поскольку они могут использовать @FuntionalInterface в качестве аннотации

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

Результат будет следующим:

Output : 7

Основная концепция выражения Lambda заключается в определении вашей собственной логики, но уже определенных аргументов. Таким образом, в приведенном выше коде вы можете изменить определение функции do из дополнения к любому другому определению, но ваши аргументы ограничены 2.

Автор: raja emani Размещён: 04.06.2018 09:56

2 плюса

61 Репутация автора

Для тех, кто занимается поиском в Интернете, хороший метод будет использоваться java.util.function.BiConsumer. например:

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

Отпечаток будет следующим: 166

Автор: Big_Bad_E Размещён: 19.08.2018 07:07

0 плюса

4612 Репутация автора

Для меня решение, которое имеет наибольший смысл, - это определить Callbackинтерфейс:

interface Callback {
    void call();
}

а затем использовать его в качестве параметра в функции, которую вы хотите вызвать:

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

Просто точность, хотя

Лямбда - это не особый интерфейс, класс или что-то еще, что вы могли бы объявить сами. Lambdaэто просто имя, присвоенное () -> {}специальному синтаксису, что обеспечивает лучшую читаемость при передаче интерфейсов одного метода в качестве параметра. Он был разработан, чтобы заменить это:

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

Итак, в приведенном выше примере, Callbackэто не лямбда, это просто обычный интерфейс; lambdaэто имя синтаксиса ярлыка, который вы можете использовать для его реализации.

Автор: Mickaël A. Размещён: 19.11.2018 03:32
Вопросы из категории :
32x32