[프로그래머스] 자바 중급 - 람다, 람다식

정현우·2021년 4월 8일
3

Java Basic

목록 보기
8/8
post-thumbnail

자바 람다(lambda)

java8에서 새롭게 추가된 람다식! 다른말로 익명 메소드(Anonymous functions)라고 한다.
현재 사용되고 있는 람다의 근간은 수학과 기초 컴퓨터과학 분야에서의 람다 대수이다!
람다 대수는 간단히 말하자면 수학에서 사용하는 함수를 보다 단순하게 표현하는 방법이다.

람다식

왜 필요성을 느끼게 되었는가

  • 인터페이스 중에서 메소드를 하나만 가지고 있는 인터페이스를 함수형 인터페이스라고 한다.
  • 예를 들어 쓰레드를 만들때 사용하는 Runnable 인터페이스의 경우 run()메소드를 하나만 가지고 있다.
  • 아래 코드로 살펴보자!
    public class LambdaExam1 {

        public static void main(String[] args) {
            new Thread(new Runnable(){public void run(){
                for(int i = 0; i < 10; i++){
                    System.out.println("hello");
                }
            }}).start();
        }   
    }
    // 이렇게 바로 start하면 좋은데..
  • 쓰레드가 실행되면 쓰레드 생성자 안에 넣은 run()메소드가 실행된다.
  • 자바는 메소드만 매개변수로 전달할 방법이 없다. 인스턴스만 전달 할 수 있다.
  • 그렇기때문에 run()메소드를 가지고 있는 Runnable객체를 만들어서 전달한다.
  • 메소드만 전달할 수 있게 할 수 없을까? 매번 객체를 생성해서 전달하기가 너무 번거롭다!
    • 이런 부분을 해결한 것이 람다표현식이다.
    public class LambdaExam1 {  
        public static void main(String[] args) {
            new Thread(()->{
                for(int i = 0; i < 10; i++){
                    System.out.println("hello");
                }
            }).start();
        }   
    }
  • ()->{ ..... } 부분이 람다식, 다른말로 익명 메소드
  • JVM은 Thread생성자를 보고 ()->{} 이 무엇인지 대상을 추론한다.
  • Thread생성자 api를 보면 Runnable인터페이스를 받아들이는 것을 알 수 있다.
  • JVM은 Thread생성자가 Runnable인터페이스를 구현한 것이 와야 하는 것을 알게 되고 람다식을 Runnable을 구현하는 객체로 자동으로 만들어서 매개변수로 넣어준다.
  • 조금만 더 찍어먹어보자

람다식 기본문법

기본문법

  • ( 매개변수목록 ) -> { 실행문 }
  • 기본적으로 괄호 열고 매개변수 목록 열거한 뒤 괄호 닫고, 하이폰 꺽새 그리고 중괄호!
  • 2개의 값을 비교하여 어떤 값이 더 큰지 구하는 compareTo()라는 메소드를 가지고 있는 Compara 인터페이스 예제를 통해 가볍게 살펴보자!
    // 2개의 값을 받아들인 후, 정수를 반환하는 메소드를 선언
    public interface Compare{
        public int compareTo(int value1, int value2);
    }
    
    
    // Compara 인터페이스를 받아들인 후, 해당 인터페이스를 이용하는 exec메소드
    // compareTo메소드가 어떻게 구현되어 있느냐에 따라서 출력되는 값이 다름
    public class CompareExam {      
        public static void exec(Compara compara){
            int k = 10;
            int m = 20;
            int value = compara.compareTo(k, m);
            System.out.println(value);
        }
        public static void main(String[] args) {    
            exec((i, j)->{
                return i - j;
            }); }

    }
  • exec((i, j)->{ return i - j; }); 이 람다식 표현이다! 출력은 -10
  1. JVM에서 exec 메서드를 찾고
  2. 매개변수 두 개를 받아들이는 게 무엇인가 찾고
  3. 해당 인터페이스가 컴페어라는 인터페이스 메서드를 확인한 뒤 매개변수 두개 인 것을 알게 될 것 이다!

추가 예제

  • 일반적인 java 형태로, car오브젝트 대상으로 비교 연산을 하는 것을 살펴보자!
  public class CarExam{
      public static void main(String[] args){
          List<Car> cars = new ArrayList<>();
          cars.add( new Car("작은차",2,800,3) );
          cars.add( new Car("봉고차",12,1500,8) );
          cars.add( new Car("중간차",5,2200,0) );
          cars.add( new Car("비싼차",5,3500,1) );
		
          // 4인 이상, 가격 2500 미만 차만 출력해 주는 것!
          printCar(cars, new CheckCarForBigAndNotExpensive());
      }

      public static void printCar(List<Car> cars, CheckCar tester){
          for(Car car : cars){
              if (tester.test(car)) {
                  System.out.println(car);
              }
          }
      }

      // just 인터페이스
      interface CheckCar{
          boolean test(Car car);
      }

      //내부클래스를 만들어서 사용합니다.
      static class CheckCarForBigAndNotExpensive implements CheckCar{
          public boolean test(Car car){
              return car.capacity >= 4 && car.price < 2500;
          }
      }
  }
  • 위 예제 그대로에서 익명 클래스 이용!
  public class CarExam{
      public static void main(String[] args){
          List<Car> cars = new ArrayList<>();
          cars.add( new Car("작은차",2,800,3) );
          cars.add( new Car("봉고차",12,1500,8) );
          cars.add( new Car("중간차",5,2200,0) );
          cars.add( new Car("비싼차",5,3500,1) );

          printCar(cars, 
              //인터페이스 CheckCar를 구현하는 익명클래스를 만듭니다.
              new CheckCar(){
                  public boolean test(Car car){
                      return car.capacity >= 4 && car.price < 2500;
                  }
              });
      }

      public static void printCar(List<Car> cars, CheckCar tester){
          for(Car car : cars){
              if (tester.test(car)) {
                  System.out.println(car);
              }
          }
      }

      interface CheckCar{
          boolean test(Car car);
      }  
  }
  • 위 예제 그대로 람다식 이용!
  public class CarExam{
      public static void main(String[] args){
          //Car객체를 만들어서 cars에 넣습니다.
          List<Car> cars = new ArrayList<>();
          cars.add( new Car("작은차",2,800,3) );
          cars.add( new Car("봉고차",12,1500,8) );
          cars.add( new Car("중간차",5,2200,0) );
          cars.add( new Car("비싼차",5,3500,1) );

          CarExam carExam = new CarExam();
          carExam.printCar(cars, 
              // 인터페이스 CheckCar의 test메소드에 대응하는 람다를 만듭니다.
              (Car car) -> { return car.capacity >= 4 && car.price < 2500; }
          );
      }

      public void printCar(List<Car> cars, CheckCar tester){
          for(Car car : cars){
              if (tester.test(car)) {
                  System.out.println(car);
              }
          }
      }

      interface CheckCar{
          boolean test(Car car);
      }  
  }

중급을 마무리 하며

최소한의 기본 지식과 예제

  • 프로그래머스 강의를 최대한 따라하면서, 그대로 정리하고 다시 살펴볼 page나 예문, 예제들을 정리하는 형식으로만 했다.
  • 알고 있던 부분은 빠르게 정리하고 다시 되새김하기 좋았다.
  • 잘 몰랐던 부분은 '고급'파트를 만들어서 철저하게 0부터 내가 직접 docs를 만들면서 정리하려고 한다.
  • 기록이 곧 지식의 기반이 된다. 지금이라도 늦지 않았으니까, 이식성 좋은 md 파일로, 철저하게! 기록을 남겨보려고 한다.

왜 java냐

  • spring을 제대로 입문해 보자는 생각으로 java를 다시 공부하는 마음으로 정리했다.
  • 여지껏 java는 기본 lib(collections 정도까지)까지만 알고 알고리즘 풀이용으로만 썻다.
    • 아이러니 하게 web개발을 철저하게 javascript로 입문하게 되면서,,
    • 더 아이러니 한게 ps하기엔 java는 구데기인 것 같다,, 차라리 python을 썻어야 했다 ㅋㅋㅋ
    • js에 익숙해지고 오히려 spring처럼 heavy(상대적으로) 한 것은 두렵고 귀찮고 싫어졌다.
  • web full stack + python process(분산형 웹 크롤러) 외주를 할때 백엔드는 철저하게 node로만 했다.
    • 나름의 restapi보일러플레이트가 있고 controller / service / model + MVC pattern 형태를 지키고 있엇지만, 큰 규모의 MVC패턴이나 spring 처럼 조직적으로 잘 나누어져 있는 프레임워크 경험이 없었기 때문에 많이 해맷다.
    • 그리고 무엇보다 이제 취업만을 위한 프로젝트 경험이 필요했다. java와 spring말이다..
  • 짝사랑만 했던 java라는 언어를 다시 처음부터 가다듬는 마음으로 살펴본다...
profile
도메인 중심의 개발, 깊이의 가치를 이해하고 “문제 해결” 에 몰두하는 개발자가 되고싶습니다. 그러기 위해 항상 새로운 것에 도전하고 노력하는 개발자가 되고 싶습니다!

0개의 댓글