JAVA
[JAVA] 람다 표현식이란? (특징, 사용 문법)
정공자씨
2024. 4. 30. 12:26
람다 표현식이 나오게 된 배경
- 자바는 모든 기능을 클래스 기반으로 작성
- 그래서 메서드를 하나 표현하려고 해도 클래스를 정의하여, 클래스 내에서 메서드를 구현해야 했음
- 이전에는 메서드를 클래스를 기반으로 구현해도 문제가 없었으나
- 빅데이터나 인공지능이 출현하게 되면서, 대량의 데이터를 병렬로 빠르게 처리해하는 경우가 발생하여
- 기존의 방식대로 프로그래밍을 하면 수행 속도 면에서 단점이 발생
- 따라서, 자바에서도 이런 기능을 효율적으로 구현하기 위해, 함수형 프로그래밍 방식인 람다식을 도입함
[ 함수형 프로그래밍 ]
- 함수형 프로그래밍은 선언적 프로그래밍
- 람다 표현식를 지원하기 전의 자바는 완전한 명령형 프로그래밍이었음
1. 명령형 프로그래밍 : 클래스에서 메서드를 정의하고, 필요할 때 그 메서드를 호출하는 명령하여 동작
2. 선언적 프로그래밍 : 데이터가 입력으로 주어지고, 데이터가 처리되는 과정(흐름)을 정의하는 것으로 동작
메서드를 구현하여 실행하는 여러가지 방법
- 인터페이스를 구현한 클래스를 만들어서 메서드를 사용
// 인터페이스 선언
interface IMinum {
int minus(int x, int y);
}
// 인터페이스를 구현한 클래스를 만들어야 함
class Minus implements IMinus {
public int minus(int x, int y) {
return x - y;
}
}
public class Main {
public static void main(String[] args) {
// Minus 클래스의 메서드 접근하기 위해 인스턴스 생성
Minus m = new Minus();
int result = m.minus(20,10);
System.out.println(result1);
}
}
2. 익명 클래스(익명 객체)로 구현하여 메서드를 사용
// 인터페이스 선언
interface IMinum {
int minus(int x, int y);
}
public class Main {
public static void main(String[] args) {
// 익명 클래스 사용하기
IMinum m = new IMinum() {
public int minus(int x, int y) {
return x - y;
}
}
int result = m.minus(20, 10);
System.out.println(result);
}
}
3. 람다식
- 기존 익명 클래스를 람다 표현식으로 더욱 짧게 표현
- 클래스를 작성하고 객체를 생성하지 않아도 메서드 사용이 가능
// 인터페이스 선언
interface IMinum {
int minus(int x, int y);
}
public class Main {
public static void main(String[] args) {
// 익명 클래스를 람다식으로 짧게 표현
IMinum m = (x, y) -> { return x - y; };
int result = m.minus(20, 10);
System.out.println(result);
}
}
람다 표현식
메서드를 하나의 식으로 표현하는 선언적 프로그래밍의 방법
- 이름 없는 함수(익명 함수)라고도 함
- 메서드 타입, 메서드 이름, 매개변수의 타입, 중괄호 { }, return문(반환값) 생략이 가능하고
- 화살표 기호 → 를 넣어서 사용
람다 표현식이 도입되기 전에는, 익명 클래스를 이용하여 인터페이스 익명 구현 객체를 사용하였음
이것을 함수형 프로그래밍을 도입하면서, 간단하게 표현할 수 있는 방법이 람다 표현식임
- 즉, 람다 표현식은 인터페이스 익명 구현 객체를 짧게 표현하여 사용함
- 그렇다고 람다 표현식와 익명 클래스가 같은 것은 아님
[ 람다 표현식과 익명 클래스 ]
람다 표현식은 익명 클래스의 형태를 짧게 표현하여 사용함
1. 익명 클래스와 사용하는 방법이 유사하지만
2. 그렇다고 익명 클래스와 람다 표현식이 같은 것은 아님
// 함수형 인터페이스 interface ICalculator { public void min(int x, int y); // 추상메서드가 1개 }
// 익명 클래스 // 인터페이스명 변수 = new 인터페이스명() {] ICalculator cal = new ICalculator() { @Override public void min(int x, int y) { System.out.println(x < y ? x : y); } } cal.min(100, 2);
// 람다 표현식 : 클래스를 작성하고, 객체를 생성하지 않아도 메서드를 사용할 수 있음 // 인터페이스명 변수명 = 람다 표현식 ICalculator cal2 = (x, y) -> System.out.println(x < y ? x : y) cal2.min(100, 2); // 2
람다 표현식 작성
- 화살표(->) 기호를 사용하여 람다 표현식 작성
(매개변수 목록) -> { 함수 구현부 }
기존 메서드를 람다식으로 바꾸기
//기존 메소드
int method (int a, int b){
return a + b;
}
- 반환 타입과 메서드 이름을 제거하고
- 매개변수의 선언부 괄호()와 몸통 {} 사이에 ->를 추가함
// 람다식으로 바꾼 메서드
(int a, int b) -> {
return a + b;
}
람다 표현식 작성 시에 유의할 사항
1. 매개변수의 타입을 추론할 수 있는 경우에는 타입을 생략 가능
2. 매개변수가 하나인 경우에는 괄호(())를 생략 가능
3. 함수의 구현부가 하나의 문장으로만으로 이루어진 경우에는 중괄호({})를 생략 가능(이때 문장에 세미콜론(;)은 붙이지 않음)
1. 함수 구현부의 문장이 1개인 경우
- 중괄호( {} ) 생략이 가능함
- 중괄호를 생략하면, 문장의 세미콜론( ; )은 반드시 제거
- return문으로만 이루어진 경우, return 키워드 제거
[ 예제 ]
- return 문으로만 이루어진 경우
// 익명 클래스
Object obj = new Objcet() {
public int methodA() {
return 10;
}
}
// 람다 표현식으로 변환
( ) → { return 10; }
// 위 람다 표현식과 같은 코드
( ) → 10
- 중괄호 생략하면, 문장의 세미콜론( ; ) 제거
// 익명 클래스
Object obj = new Objcet() {
public int methodA(int a) {
System.out.println(a);
}
}
// 람다식 코드
(int a) → System.out.println(a)
2. 매개변수의 타입을 생략할 수 있음
- 타입을 생략을 해도, 컴파일러 나름대로 생략된 타입의 위치를 추론하여 동작하기 때문
// 익명 클래스
Object obj = new Objcet() {
public int methodA(int x, int y) {
System.out.println( x + y );
}
}
// 람다식 코드
(x, y) → System.out.println( x + y )
3. 매개변수가 1개인 경우에는 괄호( () ) 를 생략할 수 있음
- 매개변수가 없으면 → 괄호 생략 불가 (X)
- 매개변수가 1개이면, 괄호 생략 가능
- 매개변수가 있으면 → 괄호 생략 가능
// 매개변수가 있으면, 괄호 생략 가능
(int a) → System.out.println(a)
a → System.out.println(a)
// 매개변수가 없으면, 괄호 생략 X
( ) → System.out.println("매개변수 없음")
// 매개변수 생략 가능
// 매개변수 1개이면, 괄호 생략 가능
(int x) → { return x*x; }
x → x*x
4. 사용하기
기본 : (int num) -> {System.out.println(num);}
단일 실행문은 중괄호 제거 : (int num) -> System.out.println(num);
단일 인자는 타입 생략 : (num) -> System.out.println(num);
단일 인자는 소괄호 제거 : num -> System.out.println(num);
인자가 없으면 소괄호 필수 : () -> System.out.println("매개변수 없음");
인자가 여러개면 소괄호 필수 : (x, y) -> System.out.println(x, y);
인자가 없고 반환값이 있으면 : () -> {return value;};
실행코드가 return문 뿐이면 return 키워드 생략 가능 : () -> value;
매개변수, 리턴타입 둘다 있으면 : (x, y) -> x+y;
[ 예제 ] 여러 가지 형태의 메서드를 람다식으로 변환하기
1. 매개변수가 없는 경우
// 기존 메서드
void methodA() {
System.out.println("메서드 출력!");
}
// 람다식으로 바꾼 메서드
( ) → {
System.out.println("메서드 출력!");
}
2. 매개변수가 있는 경우
// 기존 메서드
void methodA(int a) {
System.out.println(a);
}
// 람다식으로 변경
(int a) → {
System.out.println(a);
}
3. 리턴값이 있는 경우
// 기존 메서드
void methodA() {
return 10;
}
// 람다식으로 변경
( ) → {
return 10;
}
4. 매개변수와 리턴값이 있는 경우
// 기존 메서드
void methodA(int a, int b) {
return a + b;
}
람다 표현식 사용하기 : 함수형 인터페이스
아무런 클래스의 메서드나 추상 클래스의 메서드를 람다 표현식으로 줄일 수 있는 것이 아니고, 함수형 인터페이스만 람다식으로 표현이 가능함
[ 함수형 인터페이스 ]
- 1개의 추상메서드를 가진 인터페이스
- 인터페이스에 정의된 하나의 추상 메서드는, 함수형 인터페이스의 구현체인 람다 표현식을 실행시키는 메서드
- 즉, 람다식으로 표현이 가능한 인터페이스를 가리켜서 함수형 인터페이스
출처