ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 람다 표현식(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개의 추상메서드가 존재한다. 다른 디폴트 메서드, 필드가 있을 수 있다.
      사용하는 인터페이스에 따라 디폴트 메서드를 호출하여 새로운 객체를 생성할 수 있다.

       

       

      🎈 정리

      무명(익명) 클래스는 일회용 클래스이다.
      즉, 람다로 표현하는 것도 일회용 클래스이다.
      무명클래스를 짧게 표현하는 방식이다.

    Designed by Tistory.