JAVA

람다식(Lambda Expression)

Lahezy 2023. 3. 8.
728x90

람다식

메서드를 하나의 식으로 표현한 것 

익명 함수의 한 종류이다.

람다식을 통해서 메서드를 변수처럼 다루는 것이 가능해졌다.

작성법

//기존
반환 타입 메서드이름(매개변수 선언){ 
	문장들
}

//람다식
(매개변수 선언) -> {
	문장들
}
//람다식의 선언된 매개변수의 타입이 추론 가능한 경우 생략 가능하다(대부분 생략 가능하다)
//매개변수의 타입을 선언해야 하면 
(int a) -> a*a //와 같이 괄호 안에 타입 선언을 해야하지만
//타입을 선언하지 않아도 되는 경우라면
a -> a*a// 와 같이 생략 가능하다.

 

람다식의 장점

불필요한 코드를제거해서 코드가 간결해지고 가독성이 올라가는 장점이 있다. 또한 메서드를 전달가능하게 하면서 생산성이 높아진다. 

람다식의 단점

디버깅이 어렵고, 비슷한 기능을 하는 함수를 여러번 생성하는 경우 코드의 가독성이 떨어질 수도 있다.

 

람다식의 클래스

익명 클래스 객체와 동일하다.

인터페이스로 구현한 익명클래스의의 객체 타입으로 받아들이다.(람다식을)

이러한 람다식을 다루기 위한 인터페이스를 함수형 인터페이스라고 부른다.

void(함수형 인터페이스)와 같은 메소드를 호출할 때 (람다를 변수처럼 다루고 싶을 때) 함수형 인터페이스를 사용하면 된다

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

람다식-> 익명 객체 -> 타입 없음 (따라서 형변환을 해야하는데 인터페이스를 구현한 클래스의 객체와 동일해서 형변환을 허용하고 , 생략이 가능하다, 람다식은 Object 타입으로 형변환이 불가능하고 함수형 인터페이스로 형변환이 가능하다) 

함수형 인터페이스를 통해서 람다식을 메서드로 전달할 수 있게 된다


익명 객체를 전달을 위한 함수형 인터페이스를 사용자가 구현해야하는가?

➡ java.util.function클래스에 있는 함수형 인터페이스사용하는 게 좋다

대표적 함수형 인터페이스 4가지(java.util.function)

Supplier <T> => T get() 

➡ 매개변수 X, 반환값 O

Supplier<String> supplier = () -> "hello";
System.out.println(supplier.get());
//"hello"출력됨

 

Consumer <T>  => void accept(T t) 

매개변수 O, 반환값 X

 

Function <T, R> => R apply(T t)  

 매개변수 O, 반환값 O

 일반적인 함수이다.

 

Predicate <T> => boolean test(T t) 

 매개변수 O, 반환값 O (fuction의 변형으로 반환값이 boolean이라는 것을 제외하면 동일하다)

 조건식을 표현하는 데 사용된다.

Predicate<String> isEmptyStr = s-> s.length()==0;
String s = "";
if(isEmptyStr.test(s))  {
	System.out.println("this is emptyString");
} 
// this is emptyString이 출력된다

 

매개변수가 두 개인 함수형 인터페이스

이름 앞에 Bi를 붙여서 사용한다.(위의 인터페이스와 동일)

 

Consumer <T>  => void accept(T t, U u) 

Function <T, R> => R apply(T t, U u) 

Predicate <T> => boolean test(T t, U u) 

 

+) 만일 3개 이상의 매개변수를 갖는 함수형 인터페이스가 필요하다면 직접 만들어서 사용해야 한다.

+) 함수형 인터페이스 선언 시에는 @FunctionalInterface 어노테이션을 활용해서 함수적 인터페이스를 명시할 수 있다.

 

 

기본형 타입의 함수형 인터페이스

기본형을 사용하는 함수형 인터페이스를 사용하는 게 좋다.

 

DoubleToIntFunction => int applyAsInt(double d)

ToIntFunction <T> => int applyAsInt(T value)

IntFunction <R> => R apply(T t, U u)

ObjIntConsumer <T> => void accept (T t, U u)

 

람다식의 메서드 접근

람다식으로 메서드를 표현할 수도 있지만 람다식이 하나의 메서드만 호출하는 경우에 메서드 참조 방법으로 담다식을 간략히 적을 수 있다.

또한 람다식으로 생성자도 접근이 가능하다.

// 클래스이름::메서드 이름 
// 참조변수::메서드 이름
Function<String, Integer> f = (string s) -> Integer.parseInt(s); //기존 코드
Function<String, Integer> f = Integer::parseInt; //메서드 참조 방법을 사용한 경우

//생성자 메서드 참조
Supplice<Test> s = () -> new Test();
Supplier<Test> s = Myclass::new; //메서드 참조 사용시(생성자)

//배열 생성시 
Function<Integer, int[]> f = int[]::new;

 

참고

https://mangkyu.tistory.com/113

자바의 정석 3판

https://juyoung-1008.tistory.com/48

728x90

'JAVA' 카테고리의 다른 글

JVM의 동작 방식과 메모리 구조  (0) 2023.04.26
Stream 스트림  (0) 2023.03.19
Enum 클래스  (0) 2023.02.28
ArrayList와 LinkedList  (0) 2023.02.24
오버로딩과 오버라이딩  (0) 2023.02.22

댓글