즐겁게!! 자신있게!! 살아보세!!

재밌는 인생을 위하여! 영촤!

Language_Study/JAVA

[JAVA, App] 21.Lambda

Godwony 2020. 12. 28. 18:11
728x90
반응형

람다(Lambda)

  • 자바에서의 람다는 함수형 프로그래밍을 지원하기 위해서 1.7에서부터 지원하기 시작한 이름없는 함수

  • 메소드가 하나 뿐인 인터페이스를 구현해서 사용할 때 람다를 이용해서 대입하는 것이 가능

  • Intelli J 나 Android Studio 의 경우 메소드가 하나 뿐인 인터페이스를 anonymous를 이용해서 작성하면 람다로 자동 수정됩니다.

  • 이전의 자바는 완전한 객체 지향 언어라서 메소드의 매개변수로 함수를 대입할 수 없었습니다.
    누군가에게 작업만을 수행해달라고 요청을 해야 하는 경우 자바는 객체를 만들어서 메소드 형태로 대입한 후 요청을 했습니다.

    • 이런 이유로 자바로 작업을 요청하는 경우 시스템이 무거워졌습니다.
    • 이러한 문제를 해결하기 위해서 등장했던 언어들이 jvm을 사용하는 Scala, Closure, Kotlin 같은 언어들입니다.
    • 위의 언어들은 마지막에는 java로 번역되서 jvm위에서 실행됩니다.
  • 자바에서도 이러한 함수형 프로그래밍을 지원하기 위해서 등장시킨 개념이 람다와 스트림입니다.

    • 1.8이상에서만 사용이 가능

1.메소드가 하나 뿐인 인터페이스의 구현

  • public void run 이라는 메소드를 소유한 Runnable 이라는 인터페이스가 있습니다.
    • 이 인터페이스는 스레드를 만들어주는 인터페이스
      1) 인터페이스를 구현한 클래스를 생성하고 인스턴스를 만들어서 사용
public class RunnableImpl implements Runnable {

    @Override
    public void run() {
        //클래스를 만들어서 사용한다고 출력
        try {
            for(int i=0; i<10; i=i+1) {
                Thread.sleep(1000);
                System.out.println("클래스를 만들어서 사용");
            }
        }catch(Exception e) {
            System.out.println("예외발생:" + e.getMessage());
        }

    }
}

2) main 메소드

public class ThreadMain {

    public static void main(String[] args) {
        //Runnable 인터페이스를 구현한 클래스를 이용해서 스레드 생성 및 실행
        //인스턴스를 1개만 만들어서 사용한다면 메모리 낭비 - 클래스를 만들었기 때문에 클래스는 메모리에서 삭제가 안됨
        Thread th1 = new Thread(new RunnableImpl());
        th1.start();

        //클래스를 만들지 않고 사용 - anonymous class
        Thread th2 = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    for(int i=0; i<10; i=i+1) {
                        Thread.sleep(1000);
                        System.out.println("anonymous class 이용");
                    }
                }catch(Exception e) {
                    System.out.println("예외:" + e.getMessage());
                }
            }
        });
        th2.start();

        //람다 이용
        //인스턴스를 만드는 과정도 없고 메소드 이름도 없지만 위와 동일한 기능을 수행
        Thread th3 = new Thread(
            ()->{
                try {
                    for(int i=0; i<10; i=i+1) {
                        Thread.sleep(1000);
                        System.out.println("람다 이용");
                    }
                }catch(Exception e) {
                    System.out.println("예외:" + e.getMessage());
            }
        });

        th3.start();

    }

}

2.자바에서 람다

1) 직접 호출해서 메소드를 실행할 때는

인터페이스 변수 = 람다식;
변수.메소드();

2) 1.8 이상의 API를 사용하는 경우에는 람다식만 대입해서 메소드를 사용

3.람다식 작성 요령

(타입 매개변수, 타입 매개변수...) -> {메소드 내용 작성; return 데이터}

  • 매개변수의 자료형은 생략 가능 : 호출할 때 대입되는 데이터를 가지고 자료형을 유추
  • 매개변수가 없을 때는 ()을 해야 하지만 매개변수가 1개인 경우는 ()을 생략가능
  • 메소드 내용이 한 줄 이면 {} 해도 됨
  • 리턴 타입은 작성할 필요없고 return을 해야 하면 return 데이터; 만 해주면 됩니다.

4.람다식을 사용할 수 있는 인터페이스는 메소드가 반드시 1개만 존재해야 합니다.

  • 이러한 인터페이스는 @FuntionalInterface 라는 어노테이션을 이용해서 생성

5.람다 작성

//매개변수가 없고 리턴타입이 없는 메소드를 소유한 인터페이스
interface NoArgNoReturn{
    public void method1();
}

//매개변수가 있고 리턴 타입이 없는 경우 : 원본에 작업을 해서 원본을 변환시키거나 출력하는 인터페이스
interface ArgNoReturn{
    public void method2(int x);
}

//매개변수는 없고 리턴 타입만 있는 경우 : 거의 없는 경우
interface NoArgReturn{
    public double method3();
}

//매개변수가 있고 리턴타입이 있는 경우 - 가장 많은 경우
interface ArgReturn{
    public int method4(String str);
}

public class LambdaMain {

    public static void main(String[] args) {
        //매개변수가 없고 리턴도 없는 인터페이스 활용 
        NoArgNoReturn ob1 = () -> {System.out.println("매개변수가 없고 리턴도 없는 람다");};
        ob1.method1();

        //매개변수가 있는 경우 - 매개변수의 자료형은 생략이 가능, 매개변수가 1개인 경우는 ( )로 감싸지 않아도 됩니다.
        ArgNoReturn ob2 = (int x) ->{System.out.println(x + 10);};
        ob2.method2(100);

        //매개변수는 없고 리턴만 있는 경우 - 거의 없음
        NoArgReturn ob3 = () ->{return 10.3;};
        double d = ob3.method3();
        System.out.println(d);

        //매개변수가 있고 리턴이 있는 경우 - 데이터를 가공해서 리턴하는 함수
        ArgReturn ob4 = (str) ->{return Integer.parseInt(str);};
        int i = ob4.method4("123219");
        System.out.println(i);
    }

}

6.람다식을 사용할 수 있는 인터페이스

  • 1.8 버전 이상에서는 java.util.function 패키지에서 기본적인 람다식을 사용할 수 있는 인터페이스를 제공
    • Consumer: 매개변수는 있고 리턴 값은 없는 메소드를 소유한 인터페이스
    • Supplier: 매개변수는 없고 리턴 값만 있는 메소드를 소유한 인터페이스
    • Function: 매개변수가 있고 리턴 값도 있는 메소드를 소유한 인터페이스 - 변환
    • Operator: 매개변수가 있고 리턴 값도 있는 메소드를 소유한 인터페이스
      • 매개변수를 누적해서 연산해서 리턴하는 메소드를 소유한 인터페이스 - 연산(합계, 평균, 최대값..)
    • Predicate: 매개변수가 있는 리턴 값도 있는 메소드를 소유한 인터페이스
      • 리턴 값이 boolean
      • 조건에 맞는 데이터만 골라내는 메소드를 소유한 인터페이스
  • 기본적으로 제너릭을 적용 - 매개변수의 자료형은 Generic으로 설정
//Consumer 인터페이스는 매개변수가 1개이고 리턴타입이 없는 메소드를 소유
        Consumer <String> consumer = (t)->{System.out.println(t);};
        consumer.accept("Java Lambda");

        //Function 인터페이스는 매개변수가 1개이고 리턴타입이 있는 메소드를 소유
        //제너릭에서 앞의 자료형은 매개변수의 자료형이고 뒤의 자료형은 리턴타입의 자료형
        //데이터를 받아서 변환한 후 리턴해주는 메소드
        Function <String, String> function = (str) -> {
            if(str.length() <= 3) return str;
            else return str.substring(0, 3) + "...";};
        String r = function.apply("hi");
        System.out.println(r);
        r = function.apply("Hello World");
        System.out.println(r);
728x90
반응형

'Language_Study > JAVA' 카테고리의 다른 글

[JAVA, App] 23.Design Pattern  (0) 2020.12.28
[JAVA, App] 22.Stream API  (0) 2020.12.28
[JAVA, App] 20.Parsing  (0) 2020.12.28
[JAVA, App] 19.통신  (0) 2020.12.27
[JAVA, App] 18.Stream  (0) 2020.12.27