[JAVA] 람다와 스트림 ( Lambda & Stream ) ①

DongGyu Jung·2022년 4월 26일
0

자바(JAVA)

목록 보기
49/60
post-thumbnail

🏃‍♂️ 들어가기 앞서..

본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕

*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.


람다식을 알아보기 전에
함수형 언어란 무엇인지 짚고 넘어가자.

우리가 현재 보고있는 이 자바는 알다시피 대표적인 OOP(객체지향언어) 중 하나이다.
하지만 JDK 1.8 버전부터 이 함수형 언어의 기능을 추가시키게 되었다.

함수형 언어는 객체지향언어와 같이 비절차형 언어인데
간단하게 말하자면 " 함수 " 자체가 하나의 객체가 되어 사용되는 것이다.

동일한 입력값을 넣었을 때 항상 동일한 리턴값을 반환하고
무엇보다도 외부의 영향을 받지 않는다.


용어는 낯설 수 있겠으나
BigData 분야가 관심받기 시작하면서 함수형 언어가 필요했고
대표적인 언어로는 " Scala " 가 있으며
다들 많이 알고있는 Python 과 JavaScript도 Java와 같이 함수형 언어의 개념을 가지고 있다.



➡ 람다식 (Lambda Expression)

" 함수 (메서드) "를 간단한 식(Expression) 으로 표현하는 방법

  • 메서드의 이름반환값(return)생략된다는 점에서 " 익명 함수 (annonymous function) "이라고도 불린다.

기존의 메서드를 만들 땐,
모두 이름을 붙여주면서 블럭으로 닫아주고.. return과 매개변수 타입도 정해주고...
지켜야 할 다양한 규칙들을 지키면서
인스턴스 내에서 메서드를 선언했어야 했다.

반면 람다식을 사용할 경우,
이름과 타입 지정 등의 과정을 생략할 수 있기 때문에

간결하면서도 간편하고 이해하기 쉽다는 장점이 있다.

심지어,
식(expression)임에도 불구하고
변수처럼 사용할 수가 있는데

메서드의 매개변수로 전달되는 것도 가능함과 동시에
메서드의 결과로 반환 될 수도 있다.


📝 람다식 작성

위에서 간결하고 간편하다고 언급했다시피
만드는 방법은 간단하다.

  • 메서드의 이름반환타입을 제거 ( " 매개변수 타입 "을 추론할 수 있을 때 )
  • 선언부와 몸통{} 사이에 [ -> ] 를 추가
  • 끝에 " ; (세미콜론) " 삭제
int max(int a, int b) {
	return a > b ? a : b ;
}

// 람다식으로 변환
(a, b) -> a > b ? a : b 

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

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

추가적으로
만약 " 매개변수가 하나일 때 "는
선언부의 괄호()도 생략할 수 있고

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

x -> x * x

// 단, 매개변수가 없을 땐 "생략할 수 없다 "
int roll() {
	return (int)(Math.random() * 6) ;
}

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

" 구현부 내 문장이 한 줄일 때 "는
중괄호 생략 (블록 해제)도 가능하다.

void printProductName(String prouct, int i) {
	System.out.println(prouct+" "+i) ;
}

(product, i) -> System.out.println(prouct+" "+i)

대부분 위 방식대로 간단하게 작성할 수 있는데
" 중괄호 생략 부분 "의 경우
가끔 구현부 내 문장이 한 줄이지만 return문인 경우가 있다.
이 때는 중괄호 생략이 불가능하다.

❓ 어라? 그럼 참조변수 타입은?

여기까지 람다식을 작성하는 방법을 알아보았다.
처음에 " 람다식은 변수처럼 사용할 수 있다 "라고 언급했었다.

그러기 위해서는 만든 람다식을 참조변수를 만들어 대입한 다음, 사용하면 된다.

그런데 여기서 잠깐
Java에서는 본래 참조변수 앞에 클래스 타입을 지정해주어야한다.

하지만 위에서도 볼 수 있듯
저 람다식의 참조변수에는 어떤 타입을 지정해주어야 하는가...


참조 변수 사용법을 알아보기 앞서
이 Java의 람다식은 무엇인가를 알고가야한다.

맨위에서는 람다식을 " 익명 함수 (annonymous function) "라고 부를 수 있다고 했지만
엄밀히 따지자면
" 익명 객체 "라고 해야한다. ( 이전 게시물 - 「 객체 지향 프로그래밍Ⅱ : 익명 클래스 」 참고 )

람다식이 바로
선언과 생성을 동시에 하는
" 이름이 없는 일회용 클래스 "
즉, 익명 객체 인 것이다.

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

▼▼▼익명 객체 구현▼▼▼
/*
예시일뿐
Object로 만들고 참조변수 타입도 Object로 하면 에러 발생한다.
*/
new Object() {
	int max(int a, int b) {
    	return a > b ? a : b ;
    }
}

▼▼▼참조변수 대입 → 실패▼▼▼
Object obj = new Object() {
	int max(int a, int b) {
    	return a > b ? a : b ;
    }
};

위와 같이 new를 통해 익명 객체를 선언 및 생성하고 참조변수에도 동일하게 그 클래스 타입을 지정해줘야 하지만

예시처럼 Object같이 이미 존재하는 상위 클래스나 다른 클래스에는
해당 이름의 메서드를 가지고 있지 않기 때문에
사용할 수가 없다.

"""
그럼 인터페이스를 활용해서
추상 메서드를 사용하면 되는 것 아닌가?!!
"""

정답엔 거의 근접했지만 보통의 일반적인 인터페이스를 통한 방법으론 불가능하다.

이 때, 활용해야 하는 것은
인터페이스 중에서도 " 함수형 인터페이스(Functional Interface) "이다.

람다식 참조 변수 사용 방법 - "함수형 인터페이스" : 다음 게시물 참고

0개의 댓글