반응형

람다

장점

한 번 밖에 쓰지 않는 함수를 왜 굳이 함수로 만드느냐? 함수 재활용 X

 

단점

람다 디버깅 시 이름 없음, 주소 0

람다를 재사용해야 할 때 재사용 불가

 

웬만하면 쓰지 않도록. 차라리 private 함수로 만들기

쓰는 경우

1. 정말 한 번만 쓴다는 보장이 있는 경우

2. 코드가 정말 단순한 경우

 

[자바의 정석 - 기초편] ch14-1~4 람다식이란? 람다식 작성하기

https://youtu.be/7Kyf4mMjbTQ

람다:

함수(메서드)를 간단한 식(expression)으로 표현하는 방법

익명 함수(이름이 없는 함수)

1
2
3
int max(int a, int b){
    return a> b ? a : b;
}
cs

=> (a, b) -> a > b ? a : b

작성법

1. 메서드의 이름, 반환타입 제거하고 ->를 {} 앞에 추가

2. return 생략 가능

3. 매개변수의 타입이 추론 가능하다면 생략 가능

 

※ 람다 식은 익명 함수가 아니라, 익명 객체!

(a, b) -> a > b ? a : b

1
2
3
4
5
6
new Object() {
    int max(int a, int b){
        return a> b ? a : b;
    }
}
 
cs

 

[자바의 정석 - 기초편] ch14-5,6 함수형인터페이스

https://youtu.be/0Sp9eFRV8gE

함수형 인터페이스

단 하나의 추상 메서드만 선언된 인터페이스

1
2
3
4
interface MyFunction {
    public abstract int max(int a, int b);
}
 
cs

 

예시

1
2
3
4
5
6
7
List<String> list = Arrays.asList("abc""aaa""bbb""ddd""aaa");
 
Collections.sort(list, new Comparator<String>() {
                            public int compare(String s1, String s2) {
                                return s2.compareTo(s1);
                            }
                        });
cs

=> 아래와 동일 

1
2
3
List<String> list = Arrays.asList("abc""aaa""bbb""ddd""aaa");
 
Collections.sort(list, (s1, s2) -> s2.compareTo(s1));
cs

[자바의 정석 - 기초편] ch14-7,8 java.util.function패키지

https://youtu.be/HPxnDM_FkGc

자주 사용되는 다양한 함수형 인터페이스 제공

1) 매개변수가 1개인 함수형 인터페이스

Predicate<T> 예시

1
2
3
4
5
Predicate<String> isEmptyStr = s -> s.length() == 0;
String s = "";
 
if(isEmptyStr.test(s))
    System.out.println("This is an empty String.");
cs

2) 매개변수가 2개인 함수형 인터페이스

3) 매개변수 타입과 return 타입이 일치

예제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.util.function.*;
import java.util.*;
 
public class LambdaEx5 {
    public static void main(String[] args){
        Supplier<Integer> s = () -> (int)(Math.random()*100)+1;
        Consumer<Integer> c = i -> System.out.print(i + ", ");
        Predicate<Integer> p = i -> i%2==0;
        Function<Integer, Integer> f = i -> i/10*10;
        
        List<Integer> list = new ArrayList<>();
        makeRandomList(s, list);
        System.out.println(list);
        printEvenNum(p, c, list);
        List<Integer> newList = makeNewList(f, list);
        System.out.println(newList);
    }
    
    static <T> List<T> makeNewList(Function<T, T> f, List<T> list){
        List<T> newList = new ArrayList<T>(list.size());
        
        for(T i : list){
            newList.add(f.apply(i));
        }
        return newList;
    }
    
    static <T> void printEvenNum(Predicate<T> p, Consumer<T> c, List<T> list){
        System.out.print("[");
        for(T i : list){
            if(p.test(i)){
                c.accept(i);
            }
        }
        System.out.println("]");
    }
    
    static <T> void makeRandomList(Supplier<T> s, List<T> list){
        for(int i = 0; i<10; i++){
            list.add(s.get());
        }
    }
}
 
cs

[자바의 정석 - 기초편] ch14-9~12 Predicate의 결합. CF와 함수형 인터페이스

https://youtu.be/Kk1ZIrVZnqw

and(), or(), negate()로 두 Predicate를 하나로 결합(default 메서드)

1
2
3
4
5
6
7
Predicate<Integer> p = i -> i < 100;
Predicate<Integer> q = i -> i < 200;
Predicate<Integer> r = i -> i % 2 == 0;
 
Predicate<Integer> notP = p.negate();
Predicate<Integer> all = notP.and(q).or(r);
Predicate<Integer> all2 = notP.and(q.or(r));
cs

 

등가비교를 위한 Predicate의 작성에는 isEqual()를 사용 (static 메서드)

1
2
3
4
Predicate<Integer> p = Predicate.isEqual(str1);
 
boolean result = p.test(str2);
boolean result = Predicate.isEqual(str1).test(str2);
cs

 

예제

1
2
3
4
5
6
7
8
Function<String, Integer> f = (s) -> Integer.parseInt(s, 16);
Function<Integer, String> g = (i) -> Integer.toBinaryString(i);
 
Function<StringString> h = f.andThen(g);
Function<Integer, Integer> h2 = h.compose(g);    // g.andThen(f)와 동일
 
System.out.println(h.apply("FF"));    // "FF" -> 255 -> 11111111
System.out.println(h2.apply(2));    // 2 -> "10" -> 16
cs

 

함수형 인터페이스를 사용하는 컬렉션 프레임워크의 메서드 (와일드카드 생략)

예제 (컬렉션 프레임워크들의 코드들이 굉장히 짧아짐)

1
2
3
4
5
6
7
8
9
10
11
list.forEach(i -> System.out.print(i + ", ");    // list의 모든 요소 출력
list.removeIf(x -> x % 2 == 0 || x % 3 == 0);    // 2 또는 3의 배수 제거
list.replaceAll(i -> i * 10);                    // 모든 요소에 10을 곱함
 
// map의 모든 요소를 {k, v} 형식으로 출력
map.forEach((k, v) -> System.out.print("{" + v + ", " + v + "}, "));
 
// Iterator it = map.entrySet().iterator();
// while(it.hasNext()) {
//        System.out.println(it,next()); 
// }
cs

 

[자바의 정석 - 기초편] ch14-13,14 메서드 참조, 생성자의 메서드 참조

https://youtu.be/I55ALQndw50

메서드 참조(Method Reference)

하나의 메서드만 호출하는 람다식은 '메서드 참조'로 간단히 할 수 있음

예제

1
2
3
4
Function<String, Integer> f = (s) -> Integer.parseInt(s);
 
// 위와 동일
Function<String, Integer> f = Integer::parseInt;
cs

메서드 참조를 람다식으로 바꾸는 연습 필요

 

생성자와 메서드 참조

1
2
3
4
Supplier<MyClass> s = () -> new MyClass();
 
// 위와 동일
Supplier<MyClass> s = MyClass::new;
cs
1
2
3
4
Function<Integer, MyClass> s = (i) -> new MyClass(i);
 
// 위와 동일
Function<Integer, MyClass> s = MyClass::new;
cs

배열과 메서드 참조

1
2
3
4
Function<Integer, int[]> f = x -> new int[x];
 
// 위와 동일
Function<Integer, int[]> f2 = int[]::new;
cs
반응형

+ Recent posts