-
람다 표현식(lambda Expression)JAVA/스트림, 컬렉션 프레임워크, 람다 2024. 6. 6. 17:22
▤ 목차
✔ 람다 표현식
java SE 8부터 나온 람다 표현식은 메서드를 하나의 식으로 표현한 것을 말한다.
하나의 추상 메서드를 가지고 있는 인터페이스를 가지고 있어야 사용이 가능하다.
무명 클래스를 화살표 기호를 사용하여 짧게 줄일 수 있다.(parameter ,,,) -> { body }
만약, 람다식이 하나의 메서드를 호출하는 경우 ::으로 표현할 수 있다.
1) 클래스 이름 :: 메서드 이름 2) 참조변수 :: 메서드 이름
가독성이 좋은 쪽으로 선택하자.
💻 코드로 보기
interface HelloInter { int calcData(int a, int b); } public class MyLambda1 implements HelloInter { @Override public int calcData(int a, int b) { return a + b; } public static void main(String[] args) { System.out.println(my.calcData(3, 4)); } }
interface HelloInter { int calcData(int a, int b); } public class MyLambda1 implements HelloInter { public static void main(String[] args) { HelloInter inter = (x, y) -> x + y; System.out.println("두 수를 더한 결과 : "+inter.calcDate(4,6)); } }
클래스를 작성하고 객체를 생성하지 않아도 메서드를 사용할 수 있다.
자바에서는 클래스의 선언과 동시에 객체를 생성하므로, 단 하나의 객체만을 생성할 수 있는 클래스를 익명클래스라고 한다.
람다 표현식을 사용하면, 불필요한 코드를 줄여주고 가독성을 높여준다.👏 정리
- 매개변수가 하나인 경우 괄호()를 생략할 수 있다.
- 매개변수 타입을 추론할 수 있는 경우, 타입을 생략할 수 있다.
- body에 문장이 1개이면 중괄호{}를 생략할 수 있다.
- body에 return문 1개인 경우 중괄호{} 생략이 가능하다.
📝 인터페이스에 추상 메서드가 2개있다면?
interface HelloInter { int calcData(int a, int b); int calcData2(int a, int b); } public class MyLambda1 implements HelloInter { @Override public int calcData(int a, int b) { // 인터페이스의 추상 메서드를 오버라이딩 : 전통적인 방법 return a + b; } // // @Override // public int calcData2(int a, int b) { // return 0; // } public static void main(String[] args) { System.out.println(); HelloInter inter = (x, y) -> x + y; System.out.println(inter.calcData(4, 5)); } }
위의 경우에서는 HelloInter inter = (x, y) -> x + y; 쪽에서 아래와 같은 오류 메시지가 출력된다.
The target type of this expression must be a functional interface
추상 메서드가 1개인 경우 메서드의 이름을 사용하지 않고 찾아갈 수 있다.
💻 @FunctionalInterface
여러 개의 디폴트 메서드가 있더라도 추상 메서드가 오직 하나인 함수형 인터페이스를 말한다.
@FunctionalInterface interface HelloInter { int calcData(int a, int b); int calcData2(int a, int b); }
이런 경우, 아래와 같은 오류메시지가 나온다.
Invalid '@FunctionalInterface' annotation; HelloInter is not a functional interface
람다식은 추상메서드가 1개인 경우에 사용할 수 있다.
위의 어노테이션도 마찬가지로 추상 메서드가 오직 한 개인 함수형 인터페이스에 사용할 수 있다.
때문에 @FunctionalInterface는 람다표현식을 사용할 때 많이 사용되는 어노테이션이다.👻 정리
람다식은 객체인가? 메서드인가?
람다는 함수형 인터페이스를 구현하는 인터페이스이다.
함수형 인터페이스가 가지고 있는 1개의 추상메서드와 람다가 1:1 매칭을 하게된다.
✔ 함수형 인터페이스 (인자가 없는 추상메서드 처리)
⌨ 코드 (전통적인 방법 + 람다식 표현)
@FunctionalInterface interface MyInter { // 함수형 인터페이스 void aaa(); } public class MyLambda2 { public static void main(String[] args) { // 1. 인자가 없는 추상메서드 처리 : 전통적인 방법 MyInter inter = new MyInter() { @Override public void aaa() { System.out.println("익명 클래스의 aaa 메소드 오버라이딩"); } }; inter.aaa(); // 람다식으로 표현 1 MyInter inter2 = () -> System.out.println("일명 클래스 aaa 메서드 오버라이딩 : 람다"); inter2.aaa(); // 람다식으로 표현 2 MyInter inter3 = () -> { int imsi = 10; System.out.println("람다식으로"); System.out.println("복수의 명령문 처리"); System.out.println("imsi : " + imsi); }; inter3.aaa(); } }
✔ 인자가 있는 추상메서드 처리
💻 코드로 보기
@FunctionalInterface interface MyInterArg { void bbb(int a, int b); } public class MyLambda2 { public static void main(String[] args) { MyInterArg interArg = new MyInterArg() { @Override public void bbb(int a, int b) { System.out.println("두 수의 합은" + (a + b)); } }; interArg.bbb(3, 4); // 람다식으로 표현2 : arg가 1개일 경우 (a) -> 또는 a ->로 표현 가능 MyInterArg interArg2 = (a, b) -> System.out.println("람다로 두 수의 합은" + (a + b)); interArg2.bbb(3, 4); } }
✔ 반환값이 있고 인자가 있는 추상메서드 처리
💻 코드로 보기
@FunctionalInterface interface MyInterArgReturn { int ccc(int a, int b); } public class MyLambda2 { public static void main(String[] args) { MyInterArgReturn argReturn = new MyInterArgReturn() { @Override public int ccc(int a, int b) { System.out.println("ccc 처리"); return a + b; } }; int result = argReturn.ccc(5, 6); System.out.println("두 수를 더한 결과 : " + result); // 람다식으로 표현 3 MyInterArgReturn argReturn2 = (m, n) -> (m + n); MyInterArgReturn argReturn3 = (m, n) -> { System.out.println("람다 수행 "); return m + n; }; int result2 = argReturn3.ccc(5, 6); System.out.println("두 수를 더한 결과2 : " + result2); } }
✔ 표준 함수형 인터페이스
람다식을 사용하기 위해서 늘 함수형 인터페이스를 정의해야하는가?
아니다. 많은 사람들이 이미 만들어 놓은 함수형 인터페이스가 있다.📑 Runnable
매개변수가 없고 반환값이 없는 경우 사용할 수 있다.
📑Supplier<T>
매개 변수가 없고 반환값이 있는 경우 사용할 수 있다.
📑Consumer<T>
매개변수가 있고 반환값이 없는 경우 사용한다.
📑Function<T,R>
매개변수가 있고 반환값이 있는 경우 사용한다.
📑Predicate<T>
매개변수가 있고 반환값이 boolean형인 경우 사용한다.
표준 함수형 인터페이스 사용 장점
디폴트 메서드를 제공한다.
앞서 정리했듯 함수형 인터페이스는 1개의 추상메서드가 존재한다. 다른 디폴트 메서드, 필드가 있을 수 있다.
사용하는 인터페이스에 따라 디폴트 메서드를 호출하여 새로운 객체를 생성할 수 있다.🎈 정리
무명(익명) 클래스는 일회용 클래스이다.
즉, 람다로 표현하는 것도 일회용 클래스이다.
무명클래스를 짧게 표현하는 방식이다.'JAVA > 스트림, 컬렉션 프레임워크, 람다' 카테고리의 다른 글
Consumer 인터페이스를 사용해 DB연결하기(+ try-with-resources , 람다 ) (0) 2024.06.20 스트림 생성 (collection , 배열) (2) 2024.06.13 람다식으로 특정 확장자 파일명 불러오기 (+ forEach()와 향상된 for문) (0) 2024.06.07