본문 바로가기

Software Design Pattern

동작 파라미터화2

변화는 부분은 동작 파라미터화

Utils.sort(arr, (o1, o2) -> o2.compareTo(o1));

Utils.sort(arr, (o1, o2) -> Integer.compare(o1, o2));

Utils.sort(arr, Integer::compare);

// 람다를 호출하는 구문이 동일한 시그니쳐를 가지는 메소드를 호출하는 구문과

동일하다면, 간략하게 표현하는 것이 가능하다. - 메소드 레퍼런스

메소드 레퍼런스 : 하나의 메소드를 참조하는 람다를 편리하게 사용하는 문법.


Collections.osrt(users, (o1, o2) ->

     Integer.compare(o1.getAge(), o2.getAge())

);


Collections.osrt(users, Comparator.comparing(User::getAge)

);


람다의 원리!

1. 람다를 사용하기 위해서는 인터페이스가 정의하고 있는 추상 메소드가

한개이어야 합니다!!!!!

=> 함수형 인터페이스(Functional Interface)


interface MyPredicate {

     boolean foo(int n);

}


 또는


interface MyPredicate {

     boolean goo(int n);

}


이래도 상관없으나


interface MyPredicate {

     boolean goo(int n);

     void goo(); // 컴파일 에러

}


 이러면 안됨..


하지만 디폴트 메소드나 정적 메서드는 된다.


interface MyPredicate {

     boolean goo(int n);

     default void goo() {} // 가능

     static void hoo() {} // 가능

}


람다의 원리!

2. @Functional Interface를 이용하면, 함수형 인터페이스 조건이 성립하는지 여부를 컴파일 타임에 검증할 수 있다.


3. 람다는 익명의 클래스를 편리하게 사용하기 위해 제안된 문법이다.


익명클래스를 컴파일 했을 때 ->


Example8을 컴파일 했을 때

Example8.class

랑 익명클래스 Example8$1.class가 같이 생성됨을 알 수 있다.


람다를 컴파일 했을 때 =>

Example8을 컴파일 했을 때

Example8.class만 생성된다.. 즉 람다는 익명 클래스 메커니즘을 사용하지 않는다!!!


람다는 익명 클래스를 편리하게 사용하기 위한 문법입니다.

=> 하지만 람다는 익명 클래스와 다르게 동작합니다!!!!!


익명 클래스의 문제점

=> 컴파일러는 익명 클래스에 대응하는 클래스 파일을 생성해야 한다.

: 클래스 파일을 사용하기 위해서는 클래스 파일을 로드하고 검증하는 작업이 필요하므로

프로그램 시작에 악영향을 미친다.


확인 결과

invokedynamic 을 통해서 람다를 구현하고 있다(익명 클래스는 invokevirtual)

1) 람다 표현식의 바디를 바이트 코드로 변환하는 작업을 별도로 수행한다.

2) 람다를 처음 실행한 이후의 호출은 추가적인 비용없이 메소드를 호출 가능하다.

3) 반복적으로 호출할 경우 익명 클래스보다 빠르게 동작한다.


//


1. 프로그램은 컬랙션을 만들고 처리하는 과정이 대부분이다.

2. 사용자가 원하는 조건으로 데이터를 조직화하고 탐색을 수행한다.


=> 예전 :  명령형 언어의 기법으로 코드를 작성해야 한다.(전부 명시를 해야 한다)

x가 10이하인 좌표를 필터링해서 출력하고 싶다.

1. 필터링

2. 출력


이제는


=> 요즘의 언어 : 선언적인 코드를 작성해야 한다.

SQL 언어 안에는 데이터를 다룰 때 질의를 어떻게 구현할지에 대한 명시가 필요하지 않다.

SELECT name FROM point WHERE x <= 10


3. 자바8의 stream API를 이용하면 선언적인 코드를 통해 데이터를 처리할 수 있다.

results = points.stream().filter(point -> point.getX() <= 10).collect(Collectors.toList());

results.forEach(System.out::println);


람다는 이 스트림API를 보다 효과적으로 다루기 위해 존재한다.


results = points.parrallelStream().filter(point -> point.getX() <= 10).collect(Collectors.toList());

results.forEach(System.out::println);


C#의 LINQ

쿼리형태로 코드로 작성. 보다 효과적으로 작성


C++에서는 STL자체가 선언적인 코드 작성 관점으로 되어있음


자바8에서는 Stream API를 이해해야 함.

인텔리J를 사용하면 선언적인 코드로 변경할 수 있도록 제안해 줌.


// swift, scala, javascript, c++, c#, java8 등에서도

선언적 프로그래밍(Declarative Programming)


objective c에서 GCD


자바스크립트

언더스코어