2 분 소요

람다식

파라미터를 받아 짧은 코드 블록을 수행하고 필요에 따라 값을 return하는 표현방법

(int I, int j, ...) -> (int x = a + b; ...)
  • 파라미터 데이터 타입 생략가능

  • 파라미터가 하나인 경우 괄호 생략 가능

  • 결과를 반환하는 단일문은 괄호와 return 생략가능

    (int a, int b, ...) ->  return a + b; //return 생략가능
    () -> Math.random(); // 
    

람다식의 특징

  • 람다식 내에서 사용되는 지역변수는 final이 붙지 않아도 상수로 간주된다
  • 람다식으로 선언된 변수명은 다른 변수명과 중복될 수 없다.

람다식의 장단점

장점

  • 코드를 간결하게 만들 수 있다.
  • 식에 개발자의 의도가 명확히 드러나 가독성이 높아진다
  • 함수를 만드는 과정없이 한번에 처리할 수 있어 생산성이 높아진다
  • 병렬프로그래밍이 용이하다

단점

  • 람다를 사용하면서 만든 무명 함수는 재사용이 불가능하다
  • 디버깅이 어렵다
  • 람다를 남발하면 비슷한 함수가 중복 생성되어 코드가 지저분해질 수 있다
  • 재귀로 만들 경우에 부적합하다

함수형 인터페이스

람다는 함수형 인터페이스에 접근하여 사용된다.

함수형 인터페이스란 함수를 1급 객체 처럼 다룰 수 있게 해주는 어노테이션, 인터페이스에 선언하여 단 하나의 추상 메소드 만을 갖도록

제한하는 역활을 한다. 여기서 말하는 1급 개체란 아래 3가지 조건을 충족하는 객체를 말할 수 있다.

  • 변수나 데이터에 할당 할 수 있어야 한다
  • 객체의 인자 넘길 수 있어야 한다
  • 객체의 리턴값으로 리턴 할 수 있어야 한다

기본 함수형 인터페이스

수형 인터페이스 메서드 매개변수 반환값
java.lang.Runnable void run() X X
**Supplier** T get() X O
**Consumer** void accept(T t) O X
Function<T, R> R apply(T t) O O
**Predicate** boolean test(T t) O O

여기서 주의 깊게 봐야 하는 인터페이스는 Cousmer, Function, Predicate로 볼 수 있다.

  • Consumer

    Consumer는 객체 T를 매개변수로 받아서 사용하며, 반환값은 없는 함수형 인터페이스이다.

    사용자 정렬 구현하는 부분에서 메소드 오버라이딩을 람다식 으로 간단 진행할 수 있다.

    // 정의
    @FunctionalInterface
    public interface Consumer<T> {
      
        void accept(T t);
      
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    }
      
    // 예시
    Consumer<String> consumer = (str) -> System.out.println(str.split(" ")[0]);
    consumer.andThen(System.out::println).accept("Hello World");
      
    // 출력
    Hello
    Hello World
    
  • Function

    매개변수도 있고, 반환 값도 존재하는 일반적인 적용 함수

    import java.util.function.*;
      
    public class ETC {
    	public static void main(String[] args) {
    		// Function
    		Function<Integer, Integer> function = (num) -> num + 1;
    		int result1 = function.apply(1);
    		System.out.println(result1); // 2
              
    		Function<String, Integer> function2 = String::length; << 메소드 참조
    		int len = function2.apply("Hello World");
    		System.out.println(len);
    	}
    }
    
  • Predicate

    매개변수도 있고, 반환값 도 존재하지만, Function과 달리 Boolean 값을 반환한다.

import java.util.function.*;

public class ETC {
	public static void main(String[] args) {
		// Predicate
		Predicate<Integer> predicate = (num) -> num > 0;
		boolean result2 = predicate.test(1);
		System.out.println(result2); // true
	}
}

메소드 참조

메소드 참조란 함수형 인터페이스를 람다식이 아닌 일반 메소드를 참조시켜 선언하는 방법이다.

일반메소드의 참조 조건은 아래 3가지 와 같다

  • 함수형 인터페이스의 매개변수 타입 = 메소드의 매개변수 타입
  • 함수형 인터페이스의 매개변수 개수 = 메소드의 매개변수 개수
  • 함수형 인터페이스의 반환형 = 메소드의 반환형
종류 람다 메서드참조
static메서드 참조 (x) -> ClassName,method(x) ClassName::method
인스턴스메서드 참조 (obj, x) -> obj,method(x) ClassName::method
특종 객체 인스턴스메서드 참조 (x) -> obj,method(x) obj::method

즉 하나의 메서드만 호출하는 람다식은 ‘클래스이름:: 메서드 이름’ , ‘참조변수::메서드이름’ 으로 바꿀 수 있다.

DoubleUnaryOperator oper;

oper = (n) -> Math.abs(n); // 람다 표현식
System.out.println(oper.applyAsDouble(-5));

oper = Math::abs; // 메소드 참조
System.out.println(oper.applyAsDouble(-5));

참고 자료

https://mangkyu.tistory.com/113

태그:

카테고리:

업데이트: