이것이 자바다 Chap.14 람다식 Lambda expression(java)(KOR)
-
Upload
min-seok-koo -
Category
Education
-
view
96 -
download
5
Transcript of 이것이 자바다 Chap.14 람다식 Lambda expression(java)(KOR)
람다식
- 함수적 프로그래밍을 위해서 자바 8 부터 람다식을 지원하면서 코드 패턴이 많이 바뀌게 됨 .- 익명 함수를 생성하기 위한 식으로 객체 지향 언어보다는 함수 지향 언어에 가깝다 .- 자바 코드가 매우 간결해지고 , 컬렉션의 요소를 필터링하거나 매핑해서 원하는 결과를 쉽게 집계할 수 있다 .
Runnable runnable = new Runnable() { public void run() { ... }};
Runnable runnable = () -> { ... };
- Runnable 인터페이스의 익명구현 객체 생성 .
람다식
기본 문법
( 타입 매개변수 , ...) -> { 실행문 ; ... }
(int a) -> { System.out.println(a); }
(a) -> { System.out.println(a); }
a -> { System.out.println(a); }
람다식에서는 매개 변수의 타입을 일반적으로 언급하지 않으므로 다음처럼 .( 매개 변수 타입은 런타임 시에 대입되는 값에 따라 자동으로 인식 )
하나의 매개변수만 있으면 괄호 생략 가능 .
람다식
기본 문법
() -> { 실행문 ; ... }
(x, y) -> { return x+y ;}
(x, y) -> x+y
중괄호 안에 return 문만 있을 경우 다음과 같이 씀 .
람다식
타겟 타입
- 람다식은 메소드를 가지고 있는 객체를 생성 .
인터페이스 변수 = 람다식 ;- 람다식은 인터페이스 변수에 대입된다 .- 람다식은 인터페이스의 익명 구현 객체를 생성한다 .- 람다식은 대입될 인터페이스의 종류에 따라 작성 방법이 다르다 .- 람다식이 대입될 인터페이스를 람다식의 타겟 타입 .
람다식
함수적 인터페이스
@FunctionalInterfacepublic interface MyFunctionalInterface { public void method(); public void otherMethod(); // 컴파일 오류}
- 의미 : 하나의 추상 메소드가 선언된 인터페이스만이 람다식의 타켓 타입이 될 수 있는데 이러한 인터페이스 .- 함수적 인터페이스를 작성할 때 두 개 이상의 추상 메소드가 선언되지 않도록 컴파일러가 체킹해주는 기능 (@FunctionalInterface 어노테이션 )
람다식
매개 변수와 리턴값이 없는 람다식 ( 함수적 인터페이스 )
public class MyFunctionalInterfaceExam { public static void main(String[] args) { MyFunctionalInterface fi; // 세 람다식이 같은 의미 fi = () -> { String str = "method call1"; System.out.println(str); }; fi.method(); //----------------------------------------------------- fi = () -> { System.out.println("method call2"); }; fi.method(); //----------------------------------------------------- fi = () -> System.out.println("method call3"); fi.method(); }}
람다식
매개 변수가 있는 람다식 ( 함수적 인터페이스 )
public class MyFunctionalInterfaceExam2 { public static void main(String[] args) { MyFunctionalInterface2 fi; // 두 람다식이 같은 의미 fi = (x) -> { int result = x * 5; System.out.println(result); }; fi.method(2); //----------------------------------------------------- fi = x -> System.out.println(x * 5); fi.method(2); }}
람다식
리턴값이 있는 람다식 ( 함수적 인터페이스 )public class MyFunctionalInterfaceExam3 { public static void main(String[] args) { MyFunctionalInterface3 fi; // 네 람다식이 다 같은 의미 fi = (x, y) -> { int result = x + y; return result; }; System.out.println(fi.method(2, 5)); //--------------------------------------------------------- fi = (x, y) -> { return x + y; }; System.out.println(fi.method(2, 5)); //--------------------------------------------------------- fi = (x, y) -> x + y; System.out.println(fi.method(2, 5)); //--------------------------------------------------------- fi = (x, y) -> sum(x, y); System.out.println(fi.method(2, 5)); } public static int sum(int x, int y) { return x + y; }}
람다식
클래스 멤버와 로컬 변수 사용
- 람다식 실행 블록에는 클래스의 멤버 ( 필드와 메소드 ) 및 로컬 변수를 사용할 수 있다 .클래스 멤버의 사용
- 람다식 실행 블록에는 클래스의 멤버인 필드와 메소드를 제약 사항 없이 사용가능 .- 하지만 this 키워드를 사용할 때에는 주의 .- 일반적으로 익명 객체 내부에서 this 는 익명 객체의 참조이지만 , 람다식에서 this 는 내부적으로 생성되는 익명 객체의 참조가 아니라 람다식을 실행한 객체의 참조 .
람다식
클래스 멤버의 사용public class UsingThis { public int outterField = 10; class Inner { int innerField = 20; void method() { MyFunctionalInterface4 fi = () -> { System.out.println("Outter Field: " + outterField); System.out.println("Outter Field: " + UsingThis.this.outterField + "\n"); System.out.println("Inner Field: " + innerField); System.out.println("Inner Field: " + this.innerField + "\n"); }; fi.method(); } }}public class UsingThisExam { public static void main(String[] args) { UsingThis usingThis = new UsingThis(); UsingThis.Inner inner = usingThis.new Inner(); inner.method(); }}
중첩 객체 Inner 에서 람다식을 실행했기 때문에 람다식 내부에서의 this 는 중첩 객체 Inner 입니다 .
람다식
로컬 변수 사용
- 람다식은 메소드 내부에서 주로 작성되기 때문에 로컬 익명 구현 객체를 생성시킨다고 봐야 합니다 .- 람다식에서 바깥 클래스의 필드나 메소드는 제한 없이 사용할 수 있으나 , 메소드의 매개 변수 또는 로컬 변수를 사용하면 이 두 변수는 final 특성을 가져야 합니다 .- 따라서 매개 변수 또는 로컬 변수를 람다식에서 읽는 것은 허용되지만 , 람다식 내부 또는 외부에서 변경할 수 없습니다 .
public class UsingLocalVariable { void method(int arg) { int localVar = 40; // arg = 31; // final 특성 때문에 수정 불가 // localVar = 41; // final 특성 때문에 수정 불가 MyFunctionalInterface5 fi = () -> { System.out.println("arg: " + arg); System.out.println("localVar: " + localVar); }; fi.method(); }}
람다식
표준 API 의 함수적 인터페이스
- 자바 8 부터는 빈번하게 사용되는 함수적 인터페이스 (Functional Interface) 는 java.util.function 표준 API 패키지로 제공합니다 . - 목적 : 함수적 인터페이스를 메소드 또는 생성자의 매개 타입으로 사용하여 람다식을 대입할 수 있도록 하기 위해서 입니다 . - java.util.function 패키지의 함수적 인터페이스는 크게 Con-sumer, Supplier, Function, Operator, Predicate 로 구분됩니다 .
람다식
Consumer 함수적 인터페이스
람다식
Supplier 함수적 인터페이스
람다식
Function 함수적 인터페이스
람다식
Operator 함수적 인터페이스
람다식
Predicate 함수적 인터페이스
람다식
andThen() 과 compose() 디폴트 메소드
- Comsumer, Function, Operator 종류의 함수적 인터페이스는 andThen() 과 compose() 디폴트 메소드를 가지고 있습니다 . - andThen() 과 compose() 메소드는 두 개의 함수적 인터페이스를 순차적으로 연결하고 , 첫 번째 처리 결과를 두 번째 매개값으로 제공해서 최종 결과값을 얻을 때 사용합니다 .- andThen() 과 compose() 의 차이점은 어떤 함수적 인터페이스부터 먼저 처리하느냐에 따라 다릅니다 .
람다식
andThen() 과 compose() 디폴트 메소드
- Consumer 의 순차적 연결- Function 의 순차적 연결
람다식
and(), or(), negate() 디폴트 메소드와 isEqual() 정적 메소드- 이 메소드들은 각각 논리 연산자인 &&, ||, ! 과 대응된다 .
minBy(), maxBy() 정적 메소드
- 이 두 메소드는 매개값으로 제공되는 Comparator 를 이용해서 최대 T 와 최소 T 를 얻는 BinaryOperator<T> 를 리턴합니다 .
람다식
메소드 참조
- 메소드 참조 (Method Reference) 는 말 그대로 메소드를 참조해서 매개 변수의 정보 및 리턴 타입을 알아내어 , 람다식에서 불필요한 매개 변수를 제거하는 것이 목적입니다 .
정적 메소드와 인스턴스 메소드 참조
클래스 :: 메소드 ;
매개 변수의 메소드 참조
람다식에서 제공되는 a 매개 변수의 메소드를 호출해서 b 매개 변수를 매개값으로 사용하는 경우
(a, b) -> { a.instanceMethod(b); }Class :: instanceMethod
람다식
생성자 참조
- 생성자를 참조한다는 것은 객체 생성을 의미
(a, b) -> { return new Class(a, b); }Class :: new;