티스토리 뷰

프로그램이야기

5. 람다 이야기 1

따강아지 2022. 6. 2. 00:30

자바에서 람다는 메서드로 전달할 수 있는 익명 함수라고 할 수 있으며 이름은 없지만 파라미터, 바디, 반환 형식, 예외를 가지며 다음과 같은 특징이 있다.

람다 표현식은 함수형 인터페이스의 인스턴스(함수형 인터페이스를 구현한 클래스의 인스턴스)라 할 수 있다.

함수형 인터페이스는 디폴트 메서드를 제외한 추상 메서드가 오직 하나인 인터페이스이다.
@FunctionalInterface 어노테이션이 붙어 있는 것이 함수형 인터페이스이다.
함수 디스크립터(

람다식(Lambda Expression) 내에서 사용되는 지역 변수는 final이 붙지 않아도 상수로 간주되며, 람다식으로 선언돼 변수명은 다른 변수명과 중복될 수 없다,

1. 람다식  장점

  1. 익명 클래스처럼 많은 코드를 구현할 필요가 없어 코드가 간결핟,
  2. 읽기 수운 코드를 작성할 수 있어서 가독성이 좋아진다.
  3. 함수를 만드는 과정 없이 한 번에 처리할 수 있어 생산성이 높아진다.
  4. 병렬 프로그래밍이 용이하다.

2. 람다식 단점

  1. 람다식으로 작성한 코드는 재사용이 어려우며 디버깅이 어렵다.
  2. 비슷한 코드가 산재될 수 있어서 지저분한 코드를 만들 수 있다.
  3. 재귀로 만 들 경 우에 부적합하다.

3. 람다식

  • 형식 : 람다 파라미터 -> 람다 바디
  • 표현식 
    - (arg1, arg2...) -> { body } 
    - (params) -> expression
    - (params) -> statement
    - (params) -> { statements }
    - (int a, int b) -> {  return a + b; };
       ->
    타입 추론에 의한 타입 제거 : (a, b) -> { return a+b } ;
       ->
    무엇인가를 반환하거나 한 줄 표현식이 가능하면return 삭제 :  (a, b) -> a+b;
    - () -> System.out.println("Hello ");
       -> 파라미터없고 Hello
    출력 System.out::println;
() -> System.out.println("Hello ");             // 파라미터 없고 Hello 출력
(String s) -> { System.out.println(s); }      // String s입력 매개변수로 받아 출력
() -> 8514790                                          //파라미터 없고 8514790가 리턴
() -> { return 3.14 };                                //파라미터없고 3.14 리턴

 

4 간단한 예제

public static void main(String[] args) {

    // 람다 사용
    Runnable r1 = () -> System.out.println("Hello 람다 사용 ");

    // 익명 클래스 사용
    Runnable r2 = new Runnable() {
      @Override
      public void run() {
        System.out.println("Hello 익명 클래스 사용");
      }
    };

    process(r1);
    process(r2);
    // 직접 전달
    process(() -> System.out.println("Hello 직접 전달 "));

  }

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

결과 : 
 - Hello 람다 사용 
 - Hello 익명 클래스 사용
 - Hello 직접 전달 

소스 : https://github.com/hyomee/code/blob/main/Java/function/lamda/basic/LamdaBasicMain.java

 

GitHub - hyomee/code

Contribute to hyomee/code development by creating an account on GitHub.

github.com


5. java.util.function 함수형 인터페이스 

5-1. Predicate

/**
  * Represents a predicate (boolean-valued function) of one argument.
  * This is a functional interface whose functional method is test(Object).
  * Since: 1.8 Type
  * parameters: <T> – the type of the input to the predicate
  */
@FunctionalInterface
public interface Predicate <T> {
    boolean test(T t);
}

test 추상 메서드를 정의하며 하나의 제네릭을 인수로 받아 불리언을 반환한다,

  public static <T> List<T> filetr(List<T> ls, Predicate<T> p) {
    List<T> resuts = new ArrayList<>();

    for ( T e : ls) {
      if (p.test(e)) {
        resuts.add(e);
      }
    }

    return resuts;
  }
Predicate<Car> pCar = (Car car)-> "검정".equals(car.getColor());
List<Car> blackCar = filetr(cars, pCar);

filter 메서드는 Predicate를 인수로 받아서 결과를 boolean으로 돌려주는 함수로 (Car car) -> "검정". equals(car.getColor() 람다를 수행하여 참/거짓을 돌려준다., 참이면 resuts 객체에 추가한다,

소스 : https://github.com/hyomee/code/blob/main/Java/function/lamda/basic/JavaUtilFunctionPredicate.java

 

GitHub - hyomee/code

Contribute to hyomee/code development by creating an account on GitHub.

github.com

5-2. Consumer

/** 
   * Represents an operation that accepts a single input argument and returns no  result. Unlike most other
   * functional interfaces, Consumer is expected to operate via side-effects.
   * This is a functional interface whose functional method is accept(Object).
   * Since: 1.8
   * Type parameters: <T> – the type of the input to the operation
   */
@FunctionalInterface
public interface Consumer <T> {
  void accept(T t);
}

accept추상 메서드를 정의하며 하나의 제네릭을 인수로 받아 void를 반환한다. 즉 T형식의 객체를 인수로 받아서 어떤 작업을 하고 싶을 때 사용한다,

 public static <T> void forEach(List<T> ls, Consumer<T> c) {
     for ( T e : ls) {
      c.accept(e);
    }
  }
Consumer<Car> pCar = (Car car)-> System.out.println(car.toString());
forEach(cars, pCar);

car 객체의 내용을 출력하는 기능으로 Consumer 변수에 작업 기능을 넣고 사용하였다.

소소 : https://github.com/hyomee/code/blob/main/Java/function/lamda/basic/JavaUtilFunctionConsumer.java

 

GitHub - hyomee/code

Contribute to hyomee/code development by creating an account on GitHub.

github.com

5-3. function

/**
   * Represents a function that accepts one argument and produces a result.
   * This is a functional interface whose functional method is apply(Object).
   * Since: 1.8 Type
   * parameters: <T> – the type of the input to the function
   *                     <R> – the type of the result of the function
   */
@FunctionalInterface
public interface Function <T, R> {
    R apply(T t);
}

제너릭 형식 T를 인수로 받아서 제너릭 형식 R 객체를 반환하는 추상 메서드 apply를 정의하고 앗다.

  public static <T, R> List<String> map(List<T> ls, Function<T, R> c) {
    List<String> result = new ArrayList<>();
    for ( T e : ls) {
      result.add((String) c.apply(e));
    }
    return result;
  }
Function<Car, String> pFunction = (Car car)-> car.getCompany();
List<String> result = map(cars, pFunction);
System.out.println(result.toString());

pFunction 변수는 car를 인수로 전달받아서 car의 회사명을 리턴하는 함수로 정의하고 map 메서드에서 수행하여 객체를 반환한다,

소스 : https://github.com/hyomee/code/blob/main/Java/function/lamda/basic/JavaUtilFunctionConsumer.java

 

GitHub - hyomee/code

Contribute to hyomee/code development by creating an account on GitHub.

github.com