본문 바로가기
자바(Java)

자바 중급17 : 람다(lambda)

by codeyaki 2022. 1. 19.
반응형

해당 강의를 듣고 정리한 것입니다

https://programmers.co.kr/learn/courses/9

 

자바 중급

평가 5.0 17개의 평가 ★★★★★17 ★★★★0 ★★★0 ★★0 ★0 ds02168 2021.08.20 15:37 Yeonggwang 2021.06.28 01:48 강신우 2021.04.23 10:20 HyeonWoo Jeong 2021.04.08 17:12 이용준 2021.01.26 19:23 리뷰 더보기

programmers.co.kr


람다식(익명 메서드)

  • 인터페이스 중에서 메서드를 하나만 가지고 있는 인터페이스를 함수형 인터페이스라고 한다.
    스레드를 만들 때 사용하는 Runnable 인터페이스의 경우 run() 메서드를 하나만 가지고 있다.
  • Runnable을 이용해 스레드를 만드는 방법
public class LambdaExam {
	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();
		
	}
}
  • 스레드가 실행되면 스레드 생성자 안에 넣은 run() 메서드가 실행됨.
  • 자바는 메서드만 매개변수로 전달할 방법이 없다. 인스턴스만 전달 가능.
    따라서, run() 메서드를 가지고 있는 Runnable객체를 만들어서 전달한다!!

메서드만 전달할 수 있다면 좀 더 편리하게 프로그래밍할 수 있을 텐데, 자바는 메서드만 전달할 수 있는 방법은 없었기 때문에 매번 객체를 생성해서 매개변수로 전달해야 했다. 이러한 불편함을 해소하기 위해 나온 것이 람다 표현식!!

public class LambdaExam {
	public static void main(String[] args) {
		new Thread(()->{
			for(int i=0; i<10; i++) {
				System.out.println("hello");
			}
		}).start();
	}
}
  • ()->{... } 부분이 람다식(익명 메서드)
  • JVM은 Thread 생성자를 보고 ()-{} 이 무엇인지 대상을 추론한다.
  • Thread 생성자 api를 보면 Runnable인터페이스를 받아들이는 것을 알 수 있다.
  • JVM은 Thread 생성자가 Runnable인터페이스를 구현한 것이 와야 하는 것을 아게 되고 람다식을 Runnable을 구현하는 객체를 자동으로 만들어서 매개변수를 넣어주게 된다.

람다 기본 문법

(매개변수 목록)->{실행문}

  • 2개의 값을 비교하여 어떤 값이 더 큰지 구하는 compareTo()라는 메서드를 가지고 있는 Compare 인터페이스
    - 2개의 값을 받아들인 후, 정수를 반환하는 메서드를 선언
public interface Compare {
	public int compareTo(int value1, int value2);
}
  • Compare인터페이스를 이용하는 클래스
    - Compare 인터페이스를 받아들인 후, 해당 인터페이스를 이용하는 exec메서드
    - CompareTo 메서드가 어떻게 구현되어 있느냐에 따라서 출력되는 값이 다름
public class CompareExam {
	public static void exec(Compare compare) {
		int k = 10;
		int m = 20;
		int value = compare.compareTo(k, m);
		System.out.println(value);
	}
	
	public static void main(String[] args) {
		exec((i,j)->{ return i - j;});
	}
}

>> -10

자바는 메서드만 인자로 전달하려면 반드시 객체를 만들어 전달해야 함. Java8에 람다식 생기면서, 마치 함수만 전달하는 것처럼 간편하게 문법을 사용할 수 있게 된다.


내부클래스, 익명클래스, 람다를 왜 사용하는지 조금 더 알아보자 !!

  • Car클래스
public class Car{
    public String name;
    public int capacity;  
    public int price;
    public int age;
    
    public Car(String name, int capacity, int price, int age){
        this.name = name;
        this.capacity = capacity;
        this.price = price;
        this.age = age;
    }
    
    public String toString(){
        return name;
    }
}

 

  • main클래스
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) );
        
        printCarCheaperThan(cars, 2000);
    }
    
    public static void printCarCheaperThan(List<Car> cars, int price){
        for(Car car : cars){
            if(car.price < price){
                System.out.println(car);
            }
        }
    }
}

>>

작은차

봉고차

 

  • main클래스에 추가적으로 4인승 이상이며, 2500이하인 차를 알아보는 기능을 구현해보자.

내부클래스 사용

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;
        }
    }
}

>>

봉고차

중간차

 

익명클래스 사용

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) );
        
        //인터페이스 CheckCar를 구현하는 익명클래스를 만듭니다.
        printCar(cars, 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();
        //인터페이스 CheckCar의 test메소드에 대응하는 람다를 만듭니다.
        carExam.printCar(cars, 
            (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);
    }  
}

>> 

봉고차

중간차

  • CheckCar가 함수형 인터페이스이기때문에 람다식을 사용할 수 있다!
반응형