본문 바로가기
개발/Java

[Java] 람다와 스트림(1)

by devhooney 2022. 6. 28.
728x90

자바의 정석 챕터 14를 읽고 정리

1. 람다식

1.1 람다식이란

메소드를 식으로 표현한 것

메소드를 람다식으로 표현하면 메소드의 이름과 반환값이 없어지므로, 람다식을 '익명함수'라고 하기도 함.

- 람다식과 메소드 비교

// 람다식
int[] arr = new int[5];
Arrays.setAll(arr, (i) -> (int)(Math.random() * 5) + 1);

// 메소드
int method() {
	return (int)(Math.random() * 5) + 1);
}

 

1.2 람다식 작성하기

- 타입과 메소드명을 지우고 파라미터와 중괄호 사이에 '->'를 넣어주면 완성

// 메소드
int max(int a, int b) {
	return a > b ? a : b;
}

// 람다식
(int a, int b) -> {
	return a > b ? a : b;
}

- 파라미터의 타입이 추론 가능한 경우 생략이 가능하지만, 파라미터가 여러 개일 경우 전부 생략하거나 전부 입력해줘야 한다.

- 매개변수가 1개인 경우 괄호는 생략 가능하며, 타입을 써줄 경우 괄호 생략은 불가능하다.

- 중괄호 안에 return이 없다면 중괄호도 생략이 가능하다.

 

1.3 함수형 인터페이스

- 익명인 람다식을 호출하기 위해서는 참조변수가 있어야함

@FunctionalInterface
interface MyFunction {
	public abstract int max(int a, int b);
}

MyFunction f = (int a, int b) -> a > b ? a : b;
int big = f.max(5, 3);

- @FunctionalInterface를 붙이면, 컴파일 시 문법을 확인해준다.

- 함수형 인터페이스는 람다식과 인터페이스의 메소드가 1:1로 연결되기 위해서 하나의 추상 메소드만 정의될 수 있다.

- static메소드와 default메소드는 개수 제약이 없다.

 

함수형 인터페이스 타입의 매개변수와 반환타입

- 함수형 인터페이스 MyFunction이 정의되어 있을 때,

@FunctionalInterface
interface MyFunction {
	void myMethod();
}

- 메소드의 매개변수가 MyFunction타입이면, 메소드를 호출할 때 람다식을 참조하는 참조변수를 매개변수로 지정해야 한다.

void aMethod(MyFunction f) { // 매개변수의 타입이 함수형 인터페이스
	f.myMethod(); // MyFunction에 정의된 메소드 호출
}

...

MyFunction f = () -> System.out.println("!");
aMethod(f);

// or
aMethod(() -> System.out.println("!"));

- 또는 참조변수 없이 직접 람다식을 매개변수로 지정할 수 있다.

 

람다식의 타입과 형변환

- 함수형 인터페이스로 람다식을 참조할 수 있을 뿐, 람다식의 타입이 함수형 인터페이스의 타입과 일치하는 것은 아니다.

MyFunction f = (MyFunction) (() -> {}); // 양변의 타입이 다르므로 형변환 필요함

Object obj = (Object) (() -> {}); // 에러. 함수형 인터페이스로만 형변환 가능

// Object타입으로 형변환 하려면, 먼저 함수형 인터페이스로 변환해야함
Object obj = (Object)(MyFunction) (() -> {});
String str = ((Objec)(MyFunction) (() -> {})).toString();

외부 변수를 참조하는 람다식

void method(int i) {
	int val = 30; // 내부에서 람다식 사용 시 final로 취급된다.
    i = 10; // 에러. 상수는 변경 불가능
    
    MyFunction f = (i) -> { // 에러. 외부 지역변수와 이름 중복
    	System.our.println("i: " + i);
    }
}

 

1.6 메소드 참조

- 람다식이 하나의 메소드만 호출할 경우 '메소드 참조(Method Reference)'라는 방법으로 람다식을 간략히 할 수 있다.

// 기본
Function<String, Integer> f = (String s) -> Integer.parseInt(s);

// 메소드 참조1
Function<String, Integer> f = Integer::parseInt;

// 기본
BiFunction<String, String, Boolean> f = (s1, s2) -> s1.equals(s2);

// 메소드 참조2
BiFunction<String, String, Boolean> f = Streing::equals;

// 기본
MyClass obj = new MyClass();
Function<String, Boolean> f = (x) -> obj.equals(x);

// 메소드 참조3
Function<String, Boolean> f = obj::equals;

- 하나의 메소드만 호출하는 람다식은 '클래스이름::메소드이름' 또는 '참조변수::메소드이름'으로 바꿀 수 있다.

 

728x90

'개발 > Java' 카테고리의 다른 글

[Java] 기본 알고리즘  (0) 2022.07.07
[Java] 람다와 스트림(5)  (0) 2022.07.04
[Java] 람다와 스트림(4)  (0) 2022.07.01
[Java] 람다와 스트림(3)  (0) 2022.06.30
[Java] 람다와 스트림(2)  (0) 2022.06.29