[Java] Lambda

김한준 Hanjun Kim·2024년 4월 8일
1

TIL(New)

목록 보기
5/9

코딩테스트 연습을 하는 종종 '람다식' 으로 푸는 답변들이 종종 눈에 띄었다.

public static boolean contains(final int[] arr, final int key) {
    return Arrays.stream(arr).anyMatch(i -> i == key);
}

이러한 코드를 작성 하던 중

local variables referenced from a lambda expression must be final or effectively final
(람다 표현식에서 참조하는 지역 변수는 반드시 final이거나 사실상 final이어야 합니다.)

라는 에러를 만나게 되었고, 람다식에 대해서 정리하는 글을 쓰려고 합니다.

# 람다는 이렇게 생겼습니다.


람다식이란?

람다식은 단순히 메서드를 '하나의 식' 으로 표현한 것입니다.

간략하게 표현함으로써 메서드의 이름과 변환값이 없어지므로 '익명함수' 라고도 불립니다.

  • 장점
    • 코드가 간결해집니다.
    • 메서드를 변수처럼 다룰 수 있습니다.

  • 단점
    • 람다식을 활용해 만든 익명 함수는 재사용이 불가합니다.
    • 불필요하게 너무 사용하게 되면 오히려 가독성을 떨어 뜨릴 수 있습니다.

이러한 장단점들이 있습니다.

표현식은 굉장히 많지만 흔한 예시를 보자면,

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

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

과 같이 바꿀 수 있습니다.


람다식 사용법

반환타입과 메서드 명을 지우고, 중간을 화살표로 대체하면 람다식을 만들 수 있습니다.

  1. 메서드의 이름과 반환타입을 제거하고 '->'를 블록{}앞에 추가한다.
  2. 반환값이 있는 경우, 식이나 값만 적고 return문 생략 가능(끝에 ';' 안붙임)
  3. 매개변수의 타입이 추론 가능하면 생략 가능(대부분의 경우 생략 가능)

람다식 코드 예시1

void a(String b, int c){
	System.out.println(b + c)
}

변환 ->

(String b, int c) -> System.out.println(b + c)

람다식 코드 예시2 (Stream 사용)

보통 Stream, Map 등과 같이 사용한다.

// ArrayList 및 Generics를 활용해 배열 생성
ArrayList<String> strList = new ArrayList<>(Arrays.asList("a", "b"));
// 람다식을 활용한 맵핑 수행 (소문자 String 데이터들을 대문자화시키는 작업)
Stream<String> stream = strList.stream();
stream.map(str -> str.toUpperCase()).forEach(System.out::println);

람다 캡처링

public static void main(String[] args) {
    int i = 0;
    lambda test = () -> i++;
}

# 위 코드는 에러가 발생합니다.

local variables referenced from a lambda expression must be final or effectively final

(람다 표현식에서 참조하는 지역 변수는 반드시 final이거나 사실상 final이어야 합니다.)

사실 알고보면 단순합니다.

  • 람다식이 동작하면 람다 캡처링이 발생하면서 새로운 스택이 생성되고, 기존 스택에 있는 변수들을 들고는 있지만 수정은 불가하기 때문에 참조만 가능하다.

    * 람다 캡처링 : 기존 메서드의 스택 변수들에 대해 참조가 가능하도록 람다의 스택에 복사하는 과정(call by value)

그래서 이 변수의 값을 변경하려고 하면 오류가 나고 람다식은 변하지 않는 값, final이나 effectively final 값을 요구하는 것입니다.

  • 그렇다면 어떻게 이 현상을 방지할 수 있을까?

    • 스택 말고 다른 영역에 저장하는 값을 사용하면 됩니다.
profile
개발이 하고싶은 개발지망생

1개의 댓글

comment-user-thumbnail
2024년 4월 20일

알고리즘 풀 때, 혹은 List 자료구조를 사용 할 때 많이 쓰게되는 람다에 대해 알 수 있어서 좋았어용~~

답글 달기