람다
장점
한 번 밖에 쓰지 않는 함수를 왜 굳이 함수로 만드느냐? 함수 재활용 X
단점
람다 디버깅 시 이름 없음, 주소 0
람다를 재사용해야 할 때 재사용 불가
웬만하면 쓰지 않도록. 차라리 private 함수로 만들기
쓰는 경우
1. 정말 한 번만 쓴다는 보장이 있는 경우
2. 코드가 정말 단순한 경우
[자바의 정석 - 기초편] ch14-1~4 람다식이란? 람다식 작성하기
람다:
함수(메서드)를 간단한 식(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 함수형인터페이스
함수형 인터페이스
단 하나의 추상 메서드만 선언된 인터페이스
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패키지
자주 사용되는 다양한 함수형 인터페이스 제공
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와 함수형 인터페이스
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<String, String> 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 메서드 참조, 생성자의 메서드 참조
메서드 참조(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 |
'오늘 배운 것' 카테고리의 다른 글
스트림 요약 (0) | 2021.08.23 |
---|---|
스트림(Stream) (0) | 2021.08.21 |
Docker, Kubernetes, DevOps의 개념 (0) | 2021.08.17 |
[스프링 핵심 원리 기본] 객체지향 설계와 스프링 (0) | 2021.07.28 |
[스프링 MVC 2] 스프링 타입 컨버터(2), 파일 업로드 (0) | 2021.07.26 |