IT

Java 8에서 람다를 매개 변수로 사용하는 메소드를 어떻게 정의합니까?

lottoking 2020. 3. 8. 16:25
반응형

Java 8에서 람다를 매개 변수로 사용하는 메소드를 어떻게 정의합니까?


Java 8에서 메소드는 Lambda 표현식으로 작성 될 수 있으며 참조로 전달 될 수 있습니다 (후드에서 약간의 작업만으로). 람다가 작성되어 메소드와 함께 사용되는 많은 예제가 온라인에 있지만 람다를 매개 변수로 사용하는 메소드를 작성하는 방법에 대한 예제는 없습니다. 그 구문은 무엇입니까?

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


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

람다는 순전히 호출 사이트 구조입니다. 람다의 수신자는 람다가 관련된 것을 알 필요가 없으며 대신 적절한 방법으로 인터페이스를 허용합니다.

다시 말해, 원하는 것을 정확하게 수용하고 반환하는 기능적 인터페이스 (예 : 단일 메소드가있는 인터페이스)를 정의하거나 사용합니다.

이 Java 8에는 일반적으로 사용되는 인터페이스 유형 세트가 포함되어 있습니다 java.util.function( JavaDoc에 대한 힌트는 Maurice Naftalin 덕분입니다 ).

이 특정 사용 사례를 들어 거기 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);
}

자체 인터페이스를 사용하면 의도를보다 명확하게 나타내는 이름을 가질 수 있다는 이점이 있습니다.


Lambda 표현식을 사용하려면 고유 한 기능 인터페이스를 작성하거나 2 개의 정수가 필요하고 값으로 리턴되는 조작에 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));

    }
}

내가 만든 다른 예는 여기


매개 변수가 2 개를 초과하지 않는 함수의 경우 고유 한 인터페이스를 정의하지 않고 전달할 수 있습니다. 예를 들어

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에서 이미 사용 가능한 모든 인터페이스는 페이지참조하십시오 .


http://lambdafaq.org/lambda-resources 에서 링크 된 공개 웹 액세스 가능 Lambda 지원 Java 8 JavaDoc 버전이 있습니다. (이것은 분명히 Joachim Sauer의 답변에 대한 의견이어야하지만 의견을 추가 해야하는 평판 포인트로 내 SO 계정에 들어갈 수는 없습니다.) lambdafaq 사이트 (유지)는 이것과 다른 많은 Java에 대답합니다. 람다 질문.

NB이 답변은 Java 8 GA 문서가 공개 되기 전에 작성되었습니다 . Lambda FAQ 는 Java 8에 도입 된 기능에 대해 배우는 사람들에게 여전히 유용 할 수 있기 때문에 제 자리를 떠났습니다 .


인터넷 검색을하는 사람에게는을 사용하는 것이 좋습니다 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


람다 식을 인수로 전달할 수 있습니다. 람다 식을 인수로 전달하려면 람다 식을 인수로받는 매개 변수의 형식이 기능적인 인터페이스 유형이어야합니다.

기능적인 인터페이스가있는 경우-

interface IMyFunc {
   boolean test(int num);
}

그리고 int가 5보다 큰 경우에만 목록에 int를 추가하는 필터 메소드가 있습니다. 여기서 필터 메소드에는 매개 변수 중 하나로 IMyFunc 인터페이스가 있습니다. 이 경우 람다 식을 메서드 매개 변수의 인수로 전달할 수 있습니다.

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

나에게 가장 의미있는 해결책은 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구현하는 데 사용할 수있는 바로 가기 구문의 이름입니다.


글쎄, 그건 쉽다. 람다 표현의 목적은 기능 인터페이스를 구현하는 것입니다. 하나의 메소드 만있는 인터페이스입니다. 사전 정의 된 기능 인터페이스와 레거시 기능 인터페이스에 대한 놀라운 기사가 ​​있습니다.

어쨌든, 자신의 기능적 인터페이스를 구현하려면 그것을 만드십시오. 간단한 예를 들면 다음과 같습니다.

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

그게 다야!


Lambda는 객체가 아니라 기능 인터페이스입니다. @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 Expression의 기본 개념은 고유 한 논리를 정의하지만 이미 정의 된 인수를 정의하는 것입니다. 위의 코드에서 do 함수의 정의를 다른 정의에서 추가로 변경할 수 있지만 인수는 2로 제한됩니다.


기본적으로 lamda 표현식을 매개 변수로 전달하려면이를 보유 할 수있는 유형이 필요합니다. 정수 값과 마찬가지로 기본 int 또는 Integer 클래스 에서 보유 합니다. Java에는 lamda 표현식에 대해 별도의 유형이 없으며 대신 인터페이스를 유형으로 사용하여 인수를 보유합니다. 그러나이 인터페이스는 기능적인 인터페이스 여야합니다 .


다음을 수행하십시오 ..

당신은 선언 한 method(lambda l)당신이 이름을 가진 인터페이스를 만들 수 있습니다 싶지 모두 lambda하나 개의 추상 메소드를 선언

public int add(int a,int b);  

메소드 이름은 여기서 중요하지 않습니다.

그래서 u는 호출 할 때 MyClass.method( (a,b)->a+b)이 구현은 (a,b)->a+b전화 할 때마다 인터페이스 추가 방법 낭포에 주입 될 것이다 l.add는이 구현을 가지고의 추가를 수행 할 것입니다 abreturn l.add(2,3)반환합니다 5. -기본적으로 이것은 람다가하는 일입니다.


람다를 매개 변수로 사용하면 유연성이 있습니다. 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)
        }

    }

F 인터페이스 fi = (x)-> {return 0; };

funcUsesAnonymousOrLambda (fi);

여기에서 람다식이 인터페이스로 대체되는 방법을 볼 수 있습니다.

위의 람다 식의 특정 사용법을 설명하면 더 있습니다. 심판 람다 내에서 자바 8 람다 외부 람다에서 변수를 수정할 수 없습니다

참고 : https://stackoverflow.com/questions/13604703/how-do-i-define-a-method-which-takes-a-lambda-as-a-parameter-in-java-8



반응형