본문 바로가기

[모던 자바 인 액션] 3장 람다 표현식 - 1

* 람다란 무엇인가?

* 어디에, 어떻게 람다를 사용하는가?

* 실행 어라운드 패턴

* 함수형 인터페이스, 형식 추론

* 메서드 참조

* 람다 만들기


3.1 람다란 무엇인가?

람다 표 현식은 메서드로 전달할 수 있는 익명 함수를 단순화한 것.

- 익명 : 보통의 메서드와 달리 이름이 없으므로 익명이라 표현.

- 함수 : 람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수라고 부른다. 하지만 메서드처럼 파라미터 리스트, 바디, 반환형식, 가능한 예외 리스트를 포함한다. 

- 전달 : 람다 표현식을 메서드 인수로 전달하거나 변수로 저장할 수 있다. 

- 간결성 : 익명 클래스 처럼 많은 자질구레한 코드를 구현할 필요가 없다. 

 

Comparator<Apple> beWeight = new Comparator<Apple>() {
	public int compare(Apple a1, Apple a2) {
    	return a1.getWeight().compareTo(a2.getWieght());
    }
}

Comparator<Apple> beWeight = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight));

 

(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

람다 파라미터          화살표     람다 바디 

(parameter) -> expression

(parameter) -> { statements; }

* 파라미터 리스트 : Comparator의 compare 메서드 파라미터(사과 2개)

* 화살표 : 화살표(->)는 람다의 파라미터 리스트와 바디를 구분한다. 

* 람다 바디 : 두 사과의 무게를 비교한다. 람다의 반환값에 해당하는 표현식이다. 

 

사용 사례 람다 예제
불리언 표현식 (List<String> list) -> list.isEmpty()
객체 생성 () -> new Apple(10);
객체에서 소비 (Apple a) -> { System.out.ptinln(a.getWeight()); }
객체에서 선택/추출 (String s) -> s.length()
두 값을 조합 (int a, int b) -> a * b
두 객체 비교 (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

 

3.2 어디에, 어떻게 람다를 사용할까?

함수형 인터페이스 : 하나의 추상 메서드를 지정하는 인터페이스

람다 표현식으로 함수형 인터페이스의 추상 메서드 구현을 직접 전달할 수 있으므로 전체 표현식을 함수형 인터페이스의 인스턴스로 취급(기술적으로 따지면 함수형 인터페이스를 구현한 클래스의 인스턴스)할 수 있다.

* 함수형 인터페이스의 추상 메서드 시그니처는 람다 표현식의 시그니처를 가리킨다. 

public void process(Runnable r) {
	r.run();
}

process(() -> System.out.println("This is awesome!!"));

 3.3 람다 활용 : 실행 어라운드 패턴

public String processFile() throws IOException {
	try (
    	BufferedReader br = new BufferedReader(new FileReader("data.txt"))) {
   		return br.readLine(); // 실제 필요한 작업을 하는 행     
    }
}

자원처리에 사용하는 순환 패턴

- 자원을 열고

- 처리한 다음

- 자원을 닫는 순서

초기화 / 준비 코드
작업 A
정리/마무리 코드 

1. 동작 파라미터화를 기억하라. 

processFile의 동작을 파라미터화 하는 것이다.

String result = processFile((BufferedReader br -> br.readeList()+ br.readLine());

2. 함수형 인터페이스를 이용해서 동작 전달

 

@FuncionalInterface
public interface BufferedReaderProcessor {
	String proecess(BufferedReader b) throws IOException;
}

public String processFile(BufferedReaderProcessor p) throws IOException {}

3. 동작 실행

public String processFile(BufferedReaderProcessor p) throws IOException {
	try {
    	(BefferedReader br = new BufferedReader(new FileReader("data.txt"))) {
        	return p.process(br);
        }
    }
}

4. 람다 전달

String oneLine = processFile((BufferedReader br) -> br.readLine());

String twoLines = processFile(BufferedReader br) -> br.readLine() + br.readLine());