우테코강의정리

Lambda 란 무엇일까?

최쌈장 2023. 9. 27. 20:59

동작 파라미터화

: 함수, 즉 동작을 파라미터화 한 것이 동작 파라미터 화이다.

 

// 해당 학생들을 filter할 기준이 되는 predicate를 정의하는 인터페이스
public interface StudentPredicate {
	boolean test(Student student);
}

// 해당 학생들을 filter 하는 함수
public static List<Student> filterStudent(List<Student> students, StudentPredicate studentPredicate) {
	List<Student> filteredStudents = new ArrayList<>();
    for (Student student : students) {
    	if (studentPredicate.test(student)) {
        	filteredStudents.add(student);
        }
    }
    
    return filteredStudents;
}
// 이 함수를 동작하게 하기 위해서 어떻게 선언하는 것이 좋을까?
// 기존 방법

// 1. 별도의 파일을 통한 클래스 정의 -> 별로도 인터페이스를 정의하는 클래스를 생성함
public class AgePredicate implements StudentPredicate{
	@Override
    public boolean test(Student student) {
    	return student.getAge() >= 24;
    }
}

List<Student> filteredStudents = filterStudent(students, new AgePredicate());


// 2. 익명 클래스 사용 -> 인터페이스를 매개변수 내에서 정의하도록 구현함
List<Student> filteredStudents = filterStudent(students, new StudentPredicate() {
	@Override
    public boolean test(Student student) {
    	return student.getAge() >= 24;
    }
});


// 현재 방법
// 3. 람다 사용 -> 실제 인터페이스나 클래스로 구축하지 않아도 자체적으로 람다의 body를 구축하여 filter가 가능함
List<Student> filteredStudents = filterStudent(students, student -> student.getGpa() > 3.5);

 

 

Lambda의 형태

기본 형태 : LambdaParameters -> LambdaBody

 

1. () -> 42 // 파라미터는 없으나 반환 값은 존재한다.

2. a -> a + 1; // 파라미터 한개, 반환값은 존재한다.

 ex. List<Integer> lst = new ArrayList<>(); // 여기에 1,2,3,4,5가 들어갔다고 치자

       lst.map(a -> { a = a+1;}); // 이러면 각각 2,3,4,5,6으로 들어가게 된다.

3. (a, b) -> a + b; // 파라미터 두 개 이상, 반환 값 존재함

4. () -> {} // 여러 라인을 작성해야 할 때

 

 

람다를 사용하기 위한 조건

1. 함수형 인터페이스가 필요하다. 단, 정의되지 않은 메소드가 1개만 있어야 한다.

- @FunctionalInterface : 함수형 인터페이스임을 말해주는 어노테이션이다.

- 함수형 인터페이스가 아닐 경우 에러가 뜨게 해주는 효자같은 녀석이다!

- 즉, lambdabody를 costom화 하기 위해서 위의 어노테이션이 꼭 필요하다.

 

2. 함수형 인터페이스로써 사용할 수 있는 java의 표준 라이브러리

출처 : 우아한 테크코스 강의

 

 

익명 클래스와 lambda의 차이점?

내부적으로 익명 클래스와 lambda는 별 차이 없어보인다. 결국에는 lambda가 조금 편하게 함수형 인터페이스의 메소드를 완성시켜주는 것 아니냐? 라는 것이다.

 

하지만, 익명 클래스로 정의할 경우 새로운 클래스를 생성하게 된다. 컴파일할 경우 class가 새롭게 생성되게 된다는 것이다.

만약 해당 filter를 여러번 선언할 경우에는 수도 없이 많은 클래스가 생성되는 낭비!

출처 : 우아한테크코스 강의

그러나 Lambda는 그렇지 않다. 이것을 이해하기 위해서 동작 과정을 이해해야 한다.

Lambda는 compile 단계에서 구현되지 않고, runtime 시에 구현이 된다고 한다. 익명 클래스의 경우 java에서 class로 컴파일 되는 과정을 거쳐야 하지만, 실제로 lambda의 경우 JVM 내부에서 runtime 시 불러질 때까지 구현 지연이 된다는 것이다!

출처 :&nbsp;https://pienguin.tistory.com/entry/JAVA-%EC%9E%90%EB%B0%94-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%A8-%EC%8B%A4%ED%96%89-%EA%B3%BC%EC%A0%95-%EB%B0%8F-%EA%B8%B0%EB%B3%B8-%EA%B5%AC%EC%A1%B0

 

 

람다를 사용하면 안되는 경우

1. this를 사용할 경우

 

2. shadow variable (섀도우 변수)를 사용할 경우

- 특정 범위 내부에서만 등장하는 변수이다.

- 만약 익명 클래스 내부와, lambda 식이 구현된 클래스의 변수가 동일할 경우를 생각해보자.

- 이때 lambda의 경우 오류를 발생시키지만, 익명 클래스는 내부 자체에서 만들어진 변수로 생각해서 활용할 수 있다.

 

3. context overroding이 존재할 때 (동일한 메서드가 여러개 존재할 경우)

- lambda는 기본적으로 인터페이스의 method가 여러가지 일때, lambda의 return 값을 통해서 구분한다.

- 그러나 동일한 void이지만 매개변수만 다른 것이라면 어떨까?

- 이때 어떤 것을 호출해야 하는지 lambda 자체에서 인식할 수 없기 때문에 오류가 생긴다.

 

4. 람다 코드가 3줄을 넘어가는 경우

- 이거는 굳이 엄청나게 길어질 경우에는 따로 별도의 파일의 클래스로 구현을 통해 나타내는 것이 경제적이라는 입장이다.

 

 

 

느낀 점

lambda는 거의 활용을 안하거나 짧게 사용했던 것 같은데, 솔직히 원리를 잘 모르고 쓴 적이 많았던 것 같다.

lambda는 컴파일 시에 새로운 클래스를 생성하지 않게 해주는 경제성,

그리고 코드를 구현할 때에 짧게 활용할 수 있도록 해주는 코드 경제성 등을 위해서 등장한 것 같다.

하지만 너무 많은 것들을 담아낸다면 별로 좋지 않으니 가독성을 떨어뜨리지 않을 만큼만 활용하는 것이 좋은 듯 하다.

(실제로 간단한 filter나 사칙연산? 정도에 사용하는 것이 좋은 것 같다.)

 

 

출처 : https://www.youtube.com/watch?v=sS-_Xr5Q4V4&list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&index=193 

 

'우테코강의정리' 카테고리의 다른 글

쿠키, 세션, 토큰, 캐시  (0) 2023.10.09
Servlet & Spring web MVC  (1) 2023.10.04
Interface란?  (1) 2023.10.03
Generic이란?  (0) 2023.09.26
싱글턴 패턴과 정적 클래스  (0) 2023.09.25