Как определить метод, который принимает lambda в качестве параметра в Java 8?
В 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);
}
}
Ответы
Ответ 1
Lambdas - это просто конструкция call-site: получателю лямбда не нужно знать, что участвует Лямбда, вместо этого он принимает интерфейс с соответствующим методом.
Другими словами, вы определяете или используете функциональный интерфейс (т.е. интерфейс с одним методом), который принимает и возвращает именно то, что вы хотите.
Для этого Java 8 поставляется с набором обычно используемых типов интерфейсов в java.util.function
(благодаря Морис Нафталин за подсказку о 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);
}
Использование вашего собственного интерфейса имеет то преимущество, что вы можете иметь имена, которые более четко указывают на намерение.
Ответ 2
Чтобы использовать выражение Lambda, вам нужно либо создать свой собственный функциональный интерфейс, либо использовать функциональный интерфейс Java для работы, для которого требуется два целочисленных значения и возврат в качестве значения. 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));
}
}
Другой пример, который я создал, здесь
Ответ 3
Для функций, которые не имеют более двух параметров, вы можете передавать их без указания собственного интерфейса. Например,
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));
В BiFunction<Integer, String, List<String>>
, Integer
и String
указаны его параметры, а List<String>
- его возвращаемый тип.
Для функции с одним параметром вы можете использовать Function<T, R>
, где T
- его тип параметра и R
- тип возвращаемого значения. Обратитесь к этой странице для всех интерфейсов, которые уже доступны Java.
Ответ 4
Существует общедоступная веб-версия JavaDocs с поддержкой Lambda Java 8, ссылка на которую размещена по адресу http://lambdafaq.org/lambda-resources. (Очевидно, это должен быть комментарий к ответу Йоахима Сауэра, но я не могу войти в свою учетную запись SO с баллами репутации, которые мне нужны, чтобы добавить комментарий.) Сайт lambdafaq (я его поддерживаю) отвечает на этот и многие другие Java лямбда вопросов.
NB. Этот ответ был написан до того, как документация по Java 8 GA стала общедоступной. Я оставил его на месте, потому что Lambda FAQ может быть полезен для людей, которые знакомятся с функциями, представленными в Java 8.
Ответ 5
Выражение 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);
}
}
Ответ 6
Для тех, кто гуглит это, хорошим методом будет использование 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
Ответ 7
Для меня наиболее разумным решением является определение интерфейса 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
- это название синтаксиса ярлыка, который вы можете использовать для его реализации.
Ответ 8
Ну, это легко. Целью лямбда-выражения является реализация функционального интерфейса. Это интерфейс только с одним методом. Здесь представлена статья о предопределенных и устаревших функциональных интерфейсах.
В любом случае, если вы хотите реализовать свой собственный функциональный интерфейс, сделайте это. Просто для простого примера:
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");
}
}
Что это!
Ответ 9
Лямбда - это не объект, а функциональный интерфейс. Можно определить столько функциональных интерфейсов, сколько они смогут, используя @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
Основная концепция лямбда-выражения заключается в определении собственной логики, но уже определенных аргументов. Таким образом, в приведенном выше коде вы можете изменить определение функции do в дополнение к любому другому определению, но ваши аргументы ограничены 2.
Ответ 10
Сделайте следующее..
Вы объявили method(lambda l)
Все, что вы хотите сделать, это создать интерфейс с именем lambda
и объявить один абстрактный метод.
public int add(int a,int b);
имя метода здесь не имеет значения..
Поэтому, когда вы вызываете MyClass.method( (a,b)->a+b)
эта реализация (a,b)->a+b
будет l.add
в ваш метод добавления интерфейса. Так что всякий раз, когда вы вызываете l.add
он собирается взять эту реализацию и выполнить сложение a
и b
и return l.add(2,3)
вернет 5
. - В основном это то, что делает лямбда..
Ответ 11
В основном, чтобы передать выражение lamda в качестве параметра, нам нужен тип, в котором мы можем его хранить. Так же, как целочисленное значение, мы храним в примитиве int или классе Integer. У Java нет отдельного типа для выражения лямда, вместо этого он использует интерфейс в качестве типа для хранения аргумента. Но этот интерфейс должен быть функциональным интерфейсом.
Ответ 12
Существует гибкость в использовании параметра лямбда в качестве параметра. Это позволяет функциональное программирование в 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 (р);
Здесь выше видно, как выражение лямбда может быть заменено интерфейсом.
Выше объясняется конкретное использование лямбда-выражения, есть больше.
ссылка
Java 8 лямбда внутри лямбда не может изменять переменную из внешнего lambda