일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- 분류
- 지도학습
- deep learning
- GPT-4
- PCA
- 회귀
- 오블완
- regression
- ChatGPT
- Machine Learning
- 해커톤
- gpt
- LLM
- supervised learning
- 머신러닝
- AI
- LG
- LG Aimers 4th
- Classification
- LG Aimers
- 딥러닝
- 티스토리챌린지
- OpenAI
Archives
- Today
- Total
SYDev
[이것이 자바다] Chapter 16. 람다식 본문
1. 람다식이란?
- functional programming: 함수를 정의하고, 이 함수를 데이터 처리부로 보내 데이터를 처리하는 기법
- 데이터 처리부는 데이터만 가지고 있으며, 처리 방법이 정해져 있지 않아 외부에서 제공된 함수에 의존
- 동일한 데이터라도 어떤 함수를 제공하는지에 따라, 처리하는 결과가 다를 수 있음 -> 데이터 처리의 다형성이라고도 볼 수 있음
람다식: (매개변수, ...) -> { 처리 내용 }
- Java는 람다식을 익명 구현 객체로 변환
예를 들어, 다음과 같은 인터페이스가 존재할 때
public interface Calculable {
// abstract method
void calculate(int x, int y);
}
해당 interface의 익명 구현 객체는 다음과 같이 생성 가능
new Caculable() {
@Override
public void calcuate(int x, int y) { 처리내용 }
};
이를 람다식으로 표현하면 아래 형태 - 람다식은 인터페이스의 익명 구현 객체 -> 인터페이스 타입의 매개변수에 대입 가능
(x, y) -> { 처리내용 };
다음과 같은 Caculable 매개변수를 가진 action() method에 대입 가능
public void action(Calculable calculable) {
int x = 10;
int y = 4;
calculable.calculate(x, y); // 데이터를 제공하고 추상 메소드를 호출
}
// action method 호출
action( (x, y) -> {
int result = x + y;
System.out.println(result);
});
- 인터페이스의 익명 구현 객체를 람다식으로 표현하려면, 인터페이스가 단 하나의 abstract method만 가져야 함
- functional interface: 단 하나의 abstract method만 가지는 interface
- @FunctionalInterface: 인터페이스가 함수형 인터페이스임을 보장 -> abstract method가 하나인지 검사
2. 매개변수가 없는 람다식
() -> {
실행문;
실행문;
}
() -> 실행문 // 실행문이 하나일 경우에만 중괄호 생략 가능
- 예제 1
package ch16.sec2.exam1;
@FunctionalInterface
public interface Workable {
void work();
}
package ch16.sec2.exam1;
public class Person {
public void action(Workable workable) {
workable.work();
}
}
package ch16.sec2.exam1;
public class LambdaExample {
public static void main(String[] args) {
Person person = new Person();
// 실행문이 두 개 이상인 경우 중괄호 필요
person.action(() -> {
System.out.println("출근을 합니다.");
System.out.println("프로그래밍을 합니다.");
});
// 실행문이 한 개일 경우 중괄요 생략 가능
person.action(() -> System.out.println("퇴근합니다."));
}
}
- 예제 2
package ch16.sec2.exam2;
public class Button {
// static member interface
@FunctionalInterface
public static interface ClickListener {
// abstract method
void onClick();
}
// field
private ClickListener clickListener;
// method
public void setClickListener(ClickListener clickListener) {
this.clickListener = clickListener;
}
public void click() {
this.clickListener.onClick();
}
}
package ch16.sec2.exam2;
public class ButtonExample {
public static void main(String[] args) {
// OK 버튼 객체 생성
Button btnOk = new Button();
// OK 버튼 객체에 람다식(ClickListener 익명 구현 객체) 주입
btnOk.setClickListener(() -> {
System.out.println("OK 버튼을 클릭했습니다.");
});
// OK 버튼 클릭하기
btnOk.click();
// Cancel 버튼 객체 생성
Button btnCancel = new Button();
btnCancel.setClickListener(() -> {
System.out.println("Cancel 버튼을 클릭했습니다.");
});
// Cancel 버튼 클릭하기
btnCancel.click();
}
}
3. 매개변수가 있는 람다식
- 타입을 생략하고 작성하는 것이 일반적
- 구체적 타입 대신에 var 사용 가능
// 타입 작성
(타입 매개변수, ...) -> {
실행문;
실행문;
}
(타입 매개변수, ...) -> 실행문
// var
(var 매개변수, ...) -> {
실행문;
실행문;
}
(var 매개변수, ...) -> 실행문
// 타입 생략
(매개변수, ...) -> {
실행문;
실행문;
}
(매개변수, ...) -> 실행문
- 매개변수가 하나일 경우 괄호 생략 가능, 이때 타입 또는 var 붙일 수 없음
4. 리턴값이 있는 람다식
(매개변수, ...) -> {
실행문;
return 값;
}
// return 키워드 생략
(매개변수, ...) -> 값
- 예제
package ch16.sec4;
public class Person {
public void action(Calculable calculable) {
double result = calculable.calc(10, 4);
System.out.println("결과: " + result);
}
}
package ch16.sec4;
@FunctionalInterface
public interface Calculable {
double calc(double x, double y);
}
package ch16.sec4;
public class LambdaExample {
public static void main(String[] args) {
Person person = new Person();
// 실행문이 두 개 이상일 경우
person.action((x, y) -> {
double result = x + y;
return result;
});
// 리턴문이 하나만 있을 경우(연산식)
person.action((x, y) -> (x + y));
// 리턴문이 하나만 있을 경우(메소드 호출)
person.action((x, y) -> sum(x, y));
}
public static double sum(double x, double y) {
return (x + y);
}
}
5. 메소드 참조
- 메소드 참조는 메소드를 참조해서 매개변수의 정보 및 리턴 타입을 알아내 람다식에서 불필요한 매개변수를 제거하는 목적
- ex) 두 개의 값을 받아 큰 수를 리턴하는 Math 클래스의 max() static method를 호출하는 람다식
(left, right) -> Math.max(left, right);
위 람다식을 다음과 같이 메소드 참조로 표현 가능
Math :: max;
5.1. 정적 메소드와 인스턴스 메소드 참조
클래스 :: 메소드 // static method
참조변수 :: 메소드 // instance method
5.2. 매개변수의 메소드 참조
- 람다식에서 제공되는 a 매개변수의 메소드를 호출해서, b 매개변수값을 매개값으로 사용하는 경우 존재
(a, b) -> { a.instanceMethod(b); }
위 람다식을 다음과 같이 표현 가능
클래스 :: instanceMethod
-> 작성 방법은 static method 참조와 동일, but a의 instance method가 사용된다는 점에서 차이 존재
- 예제
package ch16.sec5.exam2;
public interface Comparable {
int compare(String a, String b);
}
package ch16.sec5.exam2;
public class Person {
public void ordering(Comparable comaprable) {
String a = "홍길동";
String b = "김길동";
int result = comaprable.compare(a, b);
if(result < 0) {
System.out.println(a + "은 " + b + "보다 앞에 옵니다.");
} else if(result == 0) {
System.out.println(a + "은 " + b + "과 같습니다.");
} else {
System.out.println(a + "은 " + b + "보다 뒤에 옵니다.");
}
}
}
package ch16.sec5.exam2;
public class MethodReferenceExample {
public static void main(String[] args) {
Person person = new Person();
// (a, b) -> a.compareToIgnoreCase(b)
person.ordering( String :: compareToIgnoreCase );
}
}
6. 생성자 참조
- 생성자 참조 -> 객체를 생성하는 것을 의미
- 람다식이 단순히 객체를 생성하고 리턴하도록 구성 -> 람다식을 생성자 참조로 대치 가능
(a, b) -> { return new 클래스(a, b); }
위 람다식을 다음과 같이 표현 가능
클래스 :: new
- 생성자가 오버로딩되어 여러 개 존재하는 경우
- 컴파일러는 functional interface의 abstract method와 동일한 매개변수 타입과 개수를 가지고 있는 생성자를 찾아 실행
- 해당 생성자가 존재하지 않으면 컴파일 오류 발생
- 예제
package ch16.sec5.exam3;
@FunctionalInterface
public interface Creatable1 {
public Member create(String id);
}
package ch16.sec5.exam3;
@FunctionalInterface
public interface Creatable2 {
public Member create(String id, String name);
}
package ch16.sec5.exam3;
public class Member {
private String id;
private String name;
public Member(String id) {
this.id = id;
System.out.println("Member(String id)");
}
public Member(String id, String name) {
this.id = id;
this.name = name;
System.out.println("Member(String id, String name)");
}
@Override
public String toString() {
String info = "{ id: " + id + ", name: " + name + " }";
return info;
}
}
package ch16.sec5.exam3;
public class Person {
public Member getMember1(Creatable1 creatable) {
String id = "winter";
Member member = creatable.create(id);
return member;
}
public Member getMember2(Creatable2 creatable) {
String id = "winter";
String name = "한겨울";
Member member = creatable.create(id, name);
return member;
}
}
package ch16.sec5.exam3;
public class ConstructorReferenceExample {
public static void main(String[] args) {
Person person = new Person();
Member m1 = person.getMember1( Member :: new );
System.out.println(m1);
System.out.println();
Member m2 = person.getMember2( Member :: new );
System.out.println(m2);
}
}
참고자료
'Programming Lang > Java' 카테고리의 다른 글
[이것이 자바다] Chapter 15. 컬렉션 자료구조 (0) | 2025.02.02 |
---|---|
[이것이 자바다] Chapter 14. 멀티 스레드 (1) | 2025.02.01 |
[이것이 자바다] Chapter 13. 제네릭 (0) | 2025.01.31 |
[이것이 자바다] Chapter 12. java.base 모듈 (0) | 2025.01.31 |
[이것이 자바다] Chapter 11. 예외 처리 (0) | 2025.01.30 |