쌩로그

람다식 - 01. 본문

Language/JAVA

람다식 - 01.

.쌩수. 2023. 5. 26. 13:31
반응형

내가 성장하는 것이 다른 사람에게 좋은 영향을 줄 수 있다.

그래서 나는 잘 되야만 한다.

나는 진짜 ㄹㅇ 조만간 잘 될 사람이다.

어차피 잘 될 것이고, 지금도 잘 된 사람이다..
어쨋든간에 나는 어잘될사다.


목차

  1. 개요
  2. 본론
      2-1. 람다식 개념
      2-2. 람다식 규칙
      2-3. 메서드를 람다식으로
          2-3-1~5 예제
          2-3-6. 예제들 답 체크
  3. 요약

1. 개요

스프링의 실무에 있는 개발자들의 여러 강의들을 접하다보니, 람다식과 스트림이 많이 보인다. 이는 그만큼 많이 쓰인다는 반증이기도 하다.

람다식과 스트림을 이번참에 한 번 정리해보고, 지금 시작단계에 있는 프로젝트에도 한번 사용해봐야될 것 같에서 이번참에 정리를 해보려고 한다.

일단은 람다식에 대해 쭉 정리를 해보려고 한다.

참고서는 자바의정석 3판 2권을 참고로 하여 포스팅하겠다.

2. 본론

2-1. 람다식 개념

자바는 원래 객체지향언어인데, 람다식을 도입함으로써, 객체지향언어인 동시에 함수형 언어의 기능까지 갖추게 되었다.

람다식은 간단하게 말하면 , 선언부와 구현부로 구성되었던 메서드를 하나의 식으로 표현한 것이다.

메서드의 이름과 반환값이 없어지기 때문에
(선언부가 통으로 날라가네..)
익명 함수라고도 한다.

원래는 하나의 메서드를 정의하려면, 클래스를 생성하고, 메서드를 정의해야했지만, 람다식이 도입됨으로 이 과정을 생략하고 메서드를 호출할 수 있게 된 것이다.

람다식은 JS의 화살표 함수와 비슷한 특징을 가지고 있다.

  1. 매개변수로 전달되어지는 것이 가능하다.
  2. 메서드의 결과로 반환될 수도 있다.

2-2. 람다식 규칙

  1. 메서드의 이름과반환타입을 제거하고, 메개변수 선언부와 몸통 사이에 ->를 추가한다.
  2. 반환 값이 있는 메서드의 경우 return문을 생략가능하다.
    • 대신에 retrun문을 생략하게 되면, 문장이 아닌 식이 되기때문에, 세미콜론(;)을 붙이지 않는다.
  3. 매개변수의 타입 또한 생략이 가능한데, 만약 두개 이상의 매개변수가 있다면, 모두 매개변수 타입을 적어주거나, 모두 생략해야한다.
  4. 매개변수가 만약 하나인 경우에는 매개변수 타입 생략도 생략이지만, 괄호를 생략할 수 있다.
    • 매개변수 타입을 적고는 괄호를 생략할 수 없다.
  5. 중괄호 안의 문장이 하나일 경우 {}를 생략할 수 있다. 단 끝에 세미콜론(;)을 붙이지 않아야 한다.
    • 만약 괄호 안의 문장이 return문일 경우 괄호를 생략할 수 없다.

2-3. 메서드를 람다식으로

아래는 책에서 나온 예제인데 람다식으로 바꿔보라고 한다.
책보고 하는 거 절대 아니고, 내가 하는거...
내가 해야 늘지;;
왜냐하면 나는 성장에 목이 말라 탈수로 죽어갈 거 같은 개발자라;;;
- 누군가의 상태메세지 인용

2-3-1. 예제 1.

int max (int a, int b) {
    return a > b ? a : b; 
}

바꿔보기 답이 세 개가 표시되어있다만, 아마 줄일 수 있는 걸 더 줄이는 과정에서 3개인거 같다.

max(int a, int b) -> { return a > b ? a : b; }

반환 타입을 없애고, 선언부와 구현부 사이에 화살표(->)만 넣었다.

(int a, int b) -> a > b ? a : b

메서드 이름을 없애고, return문을 생략했다.
그리고 문장에서 식으로 표현되기 때문에, 세미콜론(;)을 생략했다.

한 번 더 생략 가능한 것을 다 생략해보면 될 거 같다.

(a, b) -> a > b ? a : b

매개변수 타입을 다 생략했다.

2-3-2. 예제 2.

void printVar(String name, int i) {
    System.out.printIn (name+"="+i ); 
}

바꿔보기의 답이 세개로 표시되어있다. 바로 가보자.

printVar(String name, int i) -> { System.out.println(name+"="+i); }

반환 타입만 생략한 결과이다.

(String name, int i) -> System.out.println(name+"="+i)

이번엔 메서드 이름을 생략했다. 그리고 규칙 중 5번을 적용해서, {} 중괄호를 생략하고, 문장이 식이 되기 때문에 역시 세미콜론(;)을 없앴다.

(name, i) -> System.out.println(name+"="+i)

매개변수의 타입을 생략했다.

2-3-3. 예제 3.

int square (int x) {
    return x * x; 
)

이 식도 답이 3개 표시되어있다. 바로 가보자.

square(int x) -> { return x * x ; }

반환타입을 생략하고 중간에 화살표를 넣었다..

(int x) -> x * x

메서드 이름과 return문을 생략했다.
return문을 생략함으로써 문장이 식으로 표현되기 때문에, 세미콜론(;)을 없앴다.

x -> x * x

매개변수가 하나일 경우, 매개변수 타입도 그렇지만, 괄호()도 생략가능하기 때문에
괄호를 생략했다.

2-3-4 예제 4.

int roll() {
    return (int)(Math.random() * 6);
}

이 메서드는 답이 두개로 표시되어있다.

바로 가보자

roll() -> { return (int)(Math.random() * 6) ; }

반환 타입을 생략하고, 화살표를 넣었다.

음... 내가 알기론 매개변수가 없으면 () 괄호 하나로도 가능한데, 이거 후에 나올지 아니면 이미 답으로 나와있을지는 모르겠으나 일단은 해당 파트의 앞부분엔 언급되어 있지 않으므로 그냥 메서드 이름을 적고 해보겠다..

roll() -> (int)(Math.random() * 6)

return문을 생략하고, 중괄호{}를 생략했다.
그리고 식으로 표현되기 때문에, 세미콜론(;)을 생략했다.

2-3-5. 예제 5.

int sumArr(int[] arr) {
    int sum = 0;
    for(int i : arr) 
        sum += i;
    return sum;
}

얘는 답이 하나다. 그냥 줄일 수 있는걸 다 줄여보겠다. 답 모르음;;;

arr -> {
    int sum = 0;
    for(int i : arr) 
        sum += i;
    return sum;
}

반환타입과 메서드 이름을 생략하고,
매개변수가 하나이기 때문에, 매개변수 타입을 생략했으며, 괄호도 생략가능하므로, 괄호도 생략했다.

2-3-6. 예제들 답 체크

  1. 예제 1번
    (int a, int b) -> { return a > b ? a : b; }  // 첫번째
    (int a, int b) -> a > b ? a : b              // 두번째
    (a, b) -> a > b ? a : b                      // 세번째
    

///////////////////////////////////////////////
// 나의 답.
max(int a, int b) -> { return a > b ? a : b; }
(int a, int b) -> a > b ? a : b
(a, b) -> a > b ? a : b

~~음... 메서드이름 생략바로 되어있네 ㅋㅋㅋㅋㅋㅋ ~~
거의 비슷하다.
답이 똑같을 순 없다~~만, 쪼금 아쉽;;~~

2. 예제 2번
```java
// 첫번째
(String name, int i) -> 
{ System.out.println(name+"="+i); }
// 두번째
(name, i) ->
{ System.out.println(name+"="+i); }
// 세번째
(name, i) ->
    System.out.println(name+"="+i)


// 나의 답
// 첫번째 
printVar(String name, int i) -> 
{ System.out.println(name+"="=i); }
// 두번째
(String name, int i) ->
    System.out.println(name+"="+i)
// 세번째
(name, i) ->
    System.out.println(name+"="i)

그냥 마지막 예시가 맞으면 만족해야겠다.;;

  1. 예제 3
    // 첫번째
    (int x) -> x * x
    // 두번째
    (x) -> x * x
    // 세번째
    x -> x * x
    

///////////////////
// 나의답
// 첫번째
square(int x) -> {
return x * x ;
}
// 두번째
(int x) -> x * x
// 세번째
x -> x * x

마지막 동일

4. 예제 4
```java
// 첫번째
() -> { return (int)(Math.random() * 6); }
// 두번째
() -> (int)(Math.random() * 6)

////////
// 나의 답
// 첫번째
roll() -> { return (int)(Math.random() * 6); }
// 두번째
roll() -> (int)(Math.random() * 6)

음... 그냥 아는대로 할 걸 그랬다.;;;
괜찮다.. 어차피 아니깐;;;ㅋㅋㅋㅋㅋ

  1. 예제 5
    // 하나 밖에없음
    (int[] arr) -> {
     int sum = 0;
     for(int i : arr) 
         sum += i;
     return sum;
    }
    

// 나의 답
arr -> {
int sum = 0;
for(int i : arr)
sum += i;
return sum;
}


음...실험 결과 두개는 같은 식이다..

람다식이 익명 함수라서, 출력 한번 해볼랬는데, 헤맸네..
익명함수이고, 인터페이스로 선언해서 사용할 수 있다는 걸 간과해서.. 그냥 `sout`으로 출력하려다가 삽질좀 했는데...

~~하..ㅋㅋㅋㅋㅋㅋ~~
~~ANSI에 집착한 기질이 여기서도...~~

일단 익명함수로 선언을 다음과 같이한다.
```java
@FunctionalInterface  
public interface LamdaPrac {  
    int sumArr(int[] arr);  
}

그리고 이걸 구현한 클래스를 만들어야한다.

참고로 필드변수로 주려면, static을 선언해야한다. 안 그러면 Non-static셜라셜라한다.
이게 왜 static으로 줘야할까 생각했는데.....main 메서드가 static이기 때문에, static변수만 호출가능하기때문이다. ~
와나 규칙 다 까먹었다.ㅋㅋㅋㅋㅋ~~
그래서 따로 인스턴스를 생성하거나 해서 호출해야한다.
근데 익명 함수라 그냥 main함수안에서 생성 가능하니.. 그냥 main함수에서 호출하다.

public class LamdaPracImpl1 {  
    public static void main(String[] args) {  
        LamdaPrac num = (int[] arr) -> {  
            int sum = 0;  
            for (int i : arr)  
                sum += i;  
            return sum;  
        };  
        int[] arr = {1, 2, 3};  
        System.out.println(num.sumArr(arr));  
    }  
}
public class LamdaPracImpl2 {  
    public static void main(String[] args) {  
        LamdaPrac lp = arr -> {  
            int sum = 0;  
            for(int i : arr) sum += i;  
            return sum;  
        };  
        int[] arr = {1, 2, 3};  
        System.out.println(lp.sumArr(arr));  
    }  
}

Impl1, Impl2의 차이는 예제 5번의 답 차이다.

여튼 결론은 같은 거다..
후..

일단은 여기서 일단락해야겠다..ㅋㅋㅋ;;

3. 요약

  1. 람다식을 현업에서 많이 사용하는 느낌을 받았고, 이참에 정리 하기 위해 공부하게되었다.
    그리고,최근에 취업한 친구도 람다 겁나쓴다고한다.

  2. 자바는 JDK 1.8(자바 8)부터 람다식을 도입하여 객체지향 언어이면서 함수형 프로그래밍의 기능을 제공하게 되었다.

  3. 람다식의 규칙에 대해서도 살펴보았다.

  4. 민망하지만, 기본규칙 거의 까먹은 게 삽질을 좀 하게되었다.

    • 다행인 건.. 왜 안되지라는 의문점을 가지고 찾아본 것..

삽질 관련 링크
람다식 출력 도움 받음
non-static variable cannot be referenced from a static context 에러 상기한 링크

람다 겁나 많이 쓴다는 친구 블로그 -> 얘 겁나 쩔음..;;

4. 끝.

-끝-

728x90
Comments