2012-11-28 3 views
217

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

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


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

좋은 질문입니다. 그리고 당신 말이 맞습니다 : 튜토리얼에는 그 부분이 포함되어 있지 않습니다. – Martin

답변

157

주면서 순수하게 전화 사이트 구조입니다 : 람다의 수신자는 람다가 관련되어 있음을 알 필요가 없다, 대신 적절한 방법과 인터페이스를 사용할 수 있습니다.

즉, 사용자가 원하는 것을 정확히 받아들이고 반환하는 기능 인터페이스 (즉, 단일 메소드가있는 인터페이스)를 정의하거나 사용합니다.

이 Java 8에는 java.util.function에 공통적으로 사용되는 인터페이스 유형 세트가 제공됩니다 (JavaDoc에 대한 힌트는 Maurice Naftalin). 이 특정 사용 사례를 들어

a single int applyAsInt(int left, int right) methodjava.util.function.IntBinaryOperator있다, 그래서 당신은이처럼 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

사용할 내장 인터페이스가 있습니까? 아니면 내가 원하는 모든 람다에 대한 인터페이스를 만들어야합니까? – Marius

+0

설명 적 이름 딜레마에 대한 재사용성에 대한 좋은 절충안은 지정된 메소드를 재정의하지 않고 내장 인터페이스를 확장하는 것입니다. 이는 추가 코드 행 하나만 사용하여 설명이 포함 된 이름을 제공합니다. –

+0

나는 그것을 얻지 않는다. 그는 무엇이든 람다를 전달할 수 있으며 성공할 수 있습니까? 'TwoArgIntOperator'에'(int a, int b, int c)'를 전달하면 어떻게 될까요? 'TwoArgIntOperator'가 같은 서명을 가진 ** 두 ** 메소드를 가지고 있다면 어떻게 될까요? 이 대답은 혼란 스럽습니다. –

12

http://lambdafaq.org/lambda-resources에서 링크 된 람다 사용 Java 8 JavaDocs의 공개 웹 액세스 버전이 있습니다. (이것은 분명히 Joachim Sauer의 답변에 대한 코멘트가되어야하지만 코멘트를 추가해야하는 평판 포인트로 나의 SO 계정에 접속할 수 없습니다.) lambdafaq 사이트 (나는 이것을 유지하고 있습니다) -λ 질문.

+2

링크 및 해당 사이트를 유지 관리해 주셔서 감사합니다! 필자는 공개 JavaDoc에 대한 링크를 제 대답에 추가하는 자유를 가졌습니다. –

+1

사이드 노트 : Angelika Langer가 [Generics] (http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html)에 대해 작성한 내용을 Lambda를 위해 제작하고있는 것으로 보입니다. 자바는 그런 자원을 필요로합니다. –

39

람다 식을 사용하려면 고유 한 함수 인터페이스를 만들거나 두 개의 정수가 필요하며 값으로 반환되는 연산을 위해 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)); 

    } 
} 

을 정의

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

    } 
} 

I 만든 별례 그쪽 함수의 here

+0

'IntBinaryOperator' 문서에 대한 링크가 죽었습니다. – Hendrikto

+1

이것은 지금까지 발견 된 람다의 가장 좋은 예이며, 실제로 나에게 '마침내'가져다 준 유일한 사람이었습니다. – JimmySmithJR

22

인 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>>, IntegerString는 파라미터이고, List<String>은 복귀 형이다.

하나의 매개 변수와 함수의

, 당신은 Function<T, R>T이 매개 변수 유형입니다, 및 R는 반환 값의 유형을 사용할 수 있습니다. Java에서 이미 사용할 수있는 모든 인터페이스에 대해서는 page을 참조하십시오.

3

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

기능적 인터페이스가 있다면 -

interface IMyFunc { 
    boolean test(int num); 
} 

는 그리고 여기서보다 5 주 경우에만리스트에 지능을 추가 필터 방식이 있음을 필터에있어서 하나로서 funtional 인터페이스 IMyFunc을 갖는다 매개 변수의 이 경우 람다 식은 method 매개 변수에 대한 인수로 전달 될 수 있습니다.

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

매개 변수로 람다를 사용할 때 융통성이 있습니다. 그것은 자바에서 함수 프로그래밍을 가능하게합니다. (람다를 사용하는) 방법이, 사용자가 기능 인터페이스를 복용하는 방법을 정의 할 수있다 파라미터로서 다음> method_body

- 기본 구문

PARAM이다. a. 이 기능 인터페이스 내에서 선언하는 방법을 정의 할 경우, 말의 기능 인터페이스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 (fi);

위의 그림은 람다 식을 인터페이스로 대체하는 방법을 보여줍니다.

위의 내용은 람다 식의 특별한 사용법을 설명합니다. ref Java 8 lambda within a lambda can't modify variable from outer lambda

관련 문제