| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 | 29 | 30 | 31 |
- Transaction
- Spring Data JPA
- Hexagonal
- JDBC
- Adapter
- springboot
- simplejpaRepository
- Layered Architecture
- Spring
- transactional
- hexagonal architecture
- JPA
- 실무
- Today
- Total
Ezcho
[Java] 람다식표현 본문
람다식이란?
람다식은 다른말로 익명 메소드라고도 한다.
인터페이스 중에서 메소드를 하나만 가지고 있는 인터페이스를 함수형 인터페이스라고 한다. 이러한 함수형 인터페이스의 메서드를 람다식을 이용해 축소시킬 수 있다.(코드의 간결화)
-> Runable 인터페이스의 run메서드가 함수형 인터페이스의 대표적인 예시이다
- Runnable을 이용한 쓰레드 만들기
기존
public class LambdaExam1 {
public static void main(String[] args) {
new Thread(new Runnable(){public void run(){
for(int i = 0; i < 10; i++){
System.out.println("hello");
}
}}).start();
}
}
하지만 이런 Runnable 인터페이스를 통해 쓰레드를 사용하기 위해선 항상 객체로 선언해주어야 한다.
그래서 람다식에서는 아래와 같이 표현할 수 있다.
public class LambdaExam1 {
public static void main(String[] args) {
new Thread(()->{
for(int i = 0; i < 10; i++){
System.out.println("hello");
}
}).start();
}
}
() -> {for문} 을 통해 표현하였다.
- JavaVirtual Machine (JVM) 은 Thread생성자(new Thread) 를 보고 ()->{} 이 무엇인지 대상을 추론한다.
- Thread생성자 api를 보면 Runnable인터페이스를 받아들이는 것을 알 수 있다. (for문)
- JVM은 Thread생성자가 Runnable인터페이스를 구현한 것이 와야 하는 것을 알게 되고 람다식을 Runnable을 구현하는 객체로 자동으로 만들어서 매개변수로 넣어준다.
람다식 문법사용
람다식은 () -> {} 과 같은 형태로 표현한다.
아래와 같은 코드를 보자
public interface Compare{
public int compareTo(int value1, int value2);
}
value1과 value2를 비교하는 compare 인터페이스의 경우 메서드가 하나밖에 존재하지 않아 함수형 인터페이스 라고 할 수 있다.
우리는 이런 CompareTo메서드를 람다식으로 사용해 볼것이다.
public class CompareExam {
public static void exec(Compara compara){
int k = 10;
int m = 20;
int value = compara.compareTo(k, m);
System.out.println(value);
}
public static void main(String[] args) {
exec((i, j)->{
return i - j;
}); }
}
Compare 인터페이스를 이용하는 클래스 이다.
Compara 인터페이스를 받아들인 후, 해당 인터페이스를 이용하는 exec메소드 가 존재한다.
compareTo메소드가 어떻게 구현되어 있느냐에 따라서 출력되는 값이 다르다.
그럼 이제 클래스 상에서 람다식을 이용해 코드를 간결하게 쓰는법을 알아보자.
내부 클래스
클래스 안에 선언된 클래스, 즉 필드를 선언하는 위치에 있는 클래스로, 중첩 클래스 또는 인스턴스 클래스라고 부르기도 한다.
public class Inner {
class Test{
int val = 0;
public void add(){
++val;
}
}
위와 같이 구성된다.
예시를 하나 살펴보면
import java.util.*;
public class CarExam{
public static void main(String[] args){
List<Car> cars = new ArrayList<>();
cars.add( new Car("작은차",2,800,3) );
cars.add( new Car("봉고차",12,1500,8) );
cars.add( new Car("중간차",5,2200,0) );
cars.add( new Car("비싼차",5,3500,1) );
printCar(cars, new CheckCarForBigAndNotExpensive());
}
public static void printCar(List<Car> cars, CheckCar tester){
for(Car car : cars){
if (tester.test(car)) {
System.out.println(car);
}
}
}
interface CheckCar{
boolean test(Car car);
}
//내부클래스를 만들어서 사용합니다.
static class CheckCarForBigAndNotExpensive implements CheckCar{
public boolean test(Car car){
return car.capacity >= 4 && car.price < 2500;
}
}
}
위와 같은 클래스를 사용하였다. 내부클래스의 test 메서드는 capacity가 4보다 크고 price가 2500보다 작은 car객체를 소환할것이다.'
호출시에는 외부클래스.내부클래스() 식으로 사용한다.
익명클래스를 통해 더 짧게 사용해보자.
익명 클래스
같은 검색조건에 대해 익명 클래스를 이용하면 별도 클래스를 만들 필요가 없으므로 코드가 조금 더 짧아집니다.
import java.util.*;
public class CarExam{
public static void main(String[] args){
List<Car> cars = new ArrayList<>();
cars.add( new Car("작은차",2,800,3) );
cars.add( new Car("봉고차",12,1500,8) );
cars.add( new Car("중간차",5,2200,0) );
cars.add( new Car("비싼차",5,3500,1) );
printCar(cars,
//인터페이스 CheckCar를 구현하는 익명클래스를 만듭니다.
new CheckCar(){
public boolean test(Car car){
return car.capacity >= 4 && car.price < 2500;
}
});
}
public static void printCar(List<Car> cars, CheckCar tester){
for(Car car : cars){
if (tester.test(car)) {
System.out.println(car);
}
}
}
interface CheckCar{
boolean test(Car car);
}
}
람다식 표현
람다식을 이용하면 코드가 더욱더 간결해진다.
import java.util.*;
public class CarExam{
public static void main(String[] args){
//Car객체를 만들어서 cars에 넣습니다.
List<Car> cars = new ArrayList<>();
cars.add( new Car("작은차",2,800,3) );
cars.add( new Car("봉고차",12,1500,8) );
cars.add( new Car("중간차",5,2200,0) );
cars.add( new Car("비싼차",5,3500,1) );
CarExam carExam = new CarExam();
carExam.printCar(cars,
//인터페이스 CheckCar의 test메소드에 대응하는 람다를 만듭니다.
(Car car) -> { return car.capacity >= 4 && car.price < 2500; }
);
}
public void printCar(List<Car> cars, CheckCar tester){
for(Car car : cars){
if (tester.test(car)) {
System.out.println(car);
}
}
}
interface CheckCar{
boolean test(Car car);
}
}
(Car car) -> { return car.capacity >= 4 && car.price < 2500; } 라는 람다를 만들어,
public boolean test(Car car){
return car.capacity >= 4 && car.price < 2500;
}
위와 같이 존재했던 코드를 축소 시킬 수 있다.
