본문 바로가기

코딩/JAVA 공부

[JAVA] 자바의 정석 _ 람다식/ 함수형 인터페이스/ 메서드 참조

 * 람다식(Lambda Expression)

- 함수(메서드)를 간단한 식으로 표현하는 방법/ 익명 함수(anonymous function) 반환 타입, 이름을 지우기 때문에

- 함수 vs 메서드 : 클래스에 독립적이면 함수, 클래스에 종속적이면 메서드

 

* 람다식 작성하기

1. 메서드의 이름과 반환 타입을 제거하고 ->를 블록{} 앞에 추가.

2. 반환 값이 있는 경우, 식이나 값만 적고 return문 생략 가능 (끝에 ; 도 생략)

3. 매개변수의 타입이 추론 가능하면 생략 가능 (대부분의 경우 생략 가능)

int max(int a, int b){
    return a>b ? a : b;
}
(a,b) -> a>b ? a : b

- 람다식 작성 시 주의사항

1. 매개변수가 하나인 경우 괄호 생략 가능

2. 블록 안의 문장이 하나뿐일 때, 괄호 생략 가능

 

** 람다식은 익명의 객체이다! 사실 위 람다식은 아래의 객체를 선언하면서 호출하는 것.

Object O = new Object(){
    int max(int a, int b){
    	return a>b ? a : b;
    }
}
int value = o.max(3,5) // 불가, object에는 max가 없음.

람다식의 참조 변수의 타입은? 람다식의 객체를 선언하려면 참조 변수가 필요한데, 

Object로 하면, Object엔 max라는 메서드가 없기 때문에 사용 불가,,

이때 함수형 인터페이스 사용!

 

* 함수형 인터페이스

- 단 하나의 추상 메서드만 선언된 인터페이스/ 람다식을 다루기 위해 사용됨.

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

위 인터페이스를 사용해 익명 클래스 선언, 객체 생성 동시에 하기

MyFunction f = new MyFunction(){
		public int max(int a, int b){
         		  	return a>b ? a : b;
           		}
  		  };
// 이걸 람다식으로 작성하면
MyFunction f = (a,b) -> a>b ? a:b; // 여기에 메서드의 이름이 없는데 (max) 인터페이스에서 만든 이름을 사용하면 됌
int value = f.max(3,5); // ok. MyFunction에 max() 가 있음

 * 함수형 인터페이스 example

- 익명 객체를 람다식으로 대체 (sort)

List<String> list = Arrays.asList("abc", "aaa", "bbb", "ddd", "aaa");
// 정렬하기 원래 sort 메서드의 매개변수로 Comparator를 넣어주는데, 이 것의 오버라이딩이 필요함.
Collections.sort(list, new Comparator<String>(){
			public int compare(String s1, String s2){
                        	return s2.compareTo(s1);
                            }
                        });
// Comparator는함수형 인터페이스로 @FunctionalInterface 가 붙어있음. 이를 람다식으로 바꾸면
Collections.sort(list, (s1, s2) -> s2.compareTo(s1));

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

- 함수형 인터페이스 타입의 매개변수

 : 메서드가 매개변수에 함수형 인터페이스가 있으면 이를 람다식으로 받겠다는 의미!

@FunctionalInterface
interfaace MyFunction{
    void myMethod();
}

void aMethod(MyFunction f){
    f.myMethod();
}

Myfunction f = () -> System.out.println("myMethod()");
aMethod(f);

- 함수형 인터페이스 타입의 반환 타입

MyFunction myMethod(){
    MyFunction f = () -> {};
    return f
}

 

 * 메서드 참조(method reference)

- 하나의 메서드만 호출하는 람다식은 '메서드 참조' 로 더 간단히 할 수 있다.

- static 메서드 참조

Integer method(String s){ // 클래스에 들어있는 메서드
    return Integer.parseInt(s);
}

// 원래 호출할 땐 클래스의 객체를 통해 호출
int result = obj.method("123");
// 이런 번거로움 해결하기 위해 static메서드가 있음. 바로 호출 가능
int result = Integer.parseInt("123");
// 이를 람다식으로 더 간단하게
Function<String, Integer> f = (String s) -> Integer.parseInt(s);
// 이를 메서드 참조로 더 간단하게
Function<String, Integer> f = Integer::parseInt; // 메서드 참조

- 생성자와 메서드 참조

Supplier<MyClass> s = () -> new MyClass();	// 람다식
Supplier<MyClass> s2 = MyClass::new;		// 메서드 참조

Function<Integer, MyClass> s = (i) -> new MyClass(i);	// 람다식
Function<Integer, MyClass> s2 = MyClass::new;		// 메서드 참조

- 배열과 메서드 참조

Function<Integer, int[]> f = (i) -> new int[i];	// 람다식
Function<Integer, int[]> f2 = int[]::new;	// 메서드 참조