Lambda, Functional Interface ๋ฌด์จ ๊ด๊ณ
๋๋ค ํํ์์ ์๋ฐ์ ๋ฉ์๋๋ฅผ ํ๋์ ์์ผ๋ก ๊ฐ๊ฒฐํ๊ฒ ํํํ ๊ฒ์ด๋ค.
์ด์ ์๋ ์๋ฐ์์ ๋ฉ์๋๋ฅผ ํํํ๋ ค๋ฉด ํด๋์ค๋ฅผ ์ ์ํด์ผ ํ์ง๋ง, ์๋ฐ 8 ๋ถํฐ ๋๋ค์์ ์ด์ฉํด ๋ฉ์๋์ ์ด๋ฆ๊ณผ ๋ฐํ ๊ฐ์
์๋ตํ ์ ์๊ณ , ์ด๋ฅผ ๋ณ์์ ๋ฃ์ด ์ฝ๋๋ฅผ ๊ฐ๊ฒฐํ๊ฒ ํ๋ค.
1
2
3
4
5
6
int add (int a, int b) {
return a + b;
}
// ์๋์ ๊ฐ์ด ๋ณ๊ฒฝํ ์ ์๋ค.
(a, b) -> a + b;
(๋งค๊ฐ๋ณ์) -> {ํจ์ ๋ณธ๋ฌธ} ์ ํํ๋ก,
๋งค๊ฐ ๋ณ์๊ฐ ์๋ ๊ฒฝ์ฐ () ๋ฅผ ์ฌ์ฉํ๊ณ , ๋งค๊ฐ ๋ณ์๊ฐ ํ๋ ์ธ ๊ฒฝ์ฐ ๊ดํธ๋ฅผ ์๋ตํ ์ ์์ผ๋ฉฐ, ํจ์์ ๋ณธ๋ฌธ์ด ํ๋์ธ ๊ฒฝ์ฐ ์ค๊ดํธ์ return์ ์๋ตํ ์ ์๋ค.
1
2
3
4
5
6
7
8
9
10
11
// ๋งค๊ฐ๋ณ์๊ฐ ์๊ณ , ํํ์์ด ํ๋
() -> System.out.println("hello"):
// ๋งค๊ฐ ๋ณ์๊ฐ ํ๋
x -> x * x;
// ๋งค๊ฐ๋ณ์๊ฐ ์ฌ๋ฌ ๊ฐ์ด๊ณ , ๋ณธ๋ฌธ์ด ์ฌ๋ฌ ์ค
(x, y) -> {
int sum = x + y;
return sum;
}
๋๋ค์์ ์๋ฐ์์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ํ ์ ์๋๋ก ๋์์ค๋ค. ์๋ฐ์์ ์ธํฐํ์ด์ค๋ ๋ฉ์๋๋ฅผ ์ ์๋งํ๊ณ ๊ตฌํ์ ํ์ง ์๋๋ค. ๊ทธ๋์ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ํด๋์ค๋ฅผ ์์ฑํ๊ณ ๋ฉ์๋๋ฅผ ์ค๋ฒ๋ผ์ด๋ํ๋ ์์ ์ ํด์ฃผ์๋ค. ์๋ก A ์ธํฐํ์ด์ค์ void run()์ด๋ผ๋ ๋ฉ์๋๊ฐ ์์ผ๋ฉด, ์ด ๋ฉ์๋๋ฅผ ์ค์ ๋ก ๋์ํ๊ฒ ํ ๋ฐฉ๋ฒ์ด ํ์ํ๋ค.
๋๋ค๋ ์ด ์ธํฐํ์ด์ค์ ๋ฉ์๋๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์ ์ฌ์ฉ๋๋ค. Runnable ์ธํฐํ์ด์ค๊ฐ ์์ ๋, run()๋ฉ์๋๋ ๊ตฌํ๋์ง ์์๋ค.
๊ทธ๋์ ์ฐ๋ฆฌ๊ฐ ๋๋ค๋ฅผ ์ฌ์ฉํด์ run()๋ฉ์๋๋ฅผ ๊ตฌํํ ์ ์๋ค.
Runnable.java
1
2
3
4
5
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
1
2
Runnable runnable = () -> System.out.println("Hello, World!");
runnable.run();
๊ทธ๋ฌ๋ฉด ๋๋ค์์ ์ด๋ค ํน์ง์ ๊ฐ์ง๊น?
1. ์ฐ์ , ๋๋ค์์ ์ฌ์ฉํ๋ฉด ์ฝ๋๊ฐ ๊ฐ๊ฒฐํ๋ค.
1
2
3
4
5
6
7
8
9
10
// ์ต๋ช
ํด๋์ค๋ก Runnable ๊ตฌํ
Runnable r1 = new Runnable() {
@Override
public void run() {
System.out.println("Hello, World!");
}
};
// ๋๋ค ํํ์์ผ๋ก Runnable ๊ตฌํ
Runnable r2 = () -> System.out.println("Hello, World!");
3. ์ปฌ๋ ์ ์์ ์ด ๊ฐํธํ๋ค.
Java 8์์๋ Stream API์ ํจ๊ป ๋๋ค ํํ์์ ๋์ ํ์ฌ, ๋ฐ์ดํฐ ์ฒ๋ฆฌ์ ๋ณํ์ ๊ฐํธํ๊ฒ ํ ์ ์๋ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
import java.util.Arrays;
import java.util.List;
public class LambdaExample {
public static void main(String[] args) {
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
// ๋ณ๋ ฌ ์ฒ๋ฆฌ
list.parallelStream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);
}
}
2. ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๋ค.
์๋ฐ๋ ๊ฐ์ฒด ์งํฅ ์ธ์ด์ง๋ง, ๋๋ค๋ฅผ ํตํด ์ผ๊ธ ๊ฐ์ฒด๋ก ํจ์๋ฅผ ๋ค๋ฃฐ ์ ์๋ค.
์ต๋ช ํจ์๋?
์ด๋ฆ์ด ์๋ ํจ์๋ก, ์ต๋ช ํจ์๋ ๋ชจ๋ ์ผ๊ธ ๊ฐ์ฒด์ด๋ค. ์ผ๊ธ ๊ฐ์ฒด์ธ ํจ์๋ ๋ณ์์ฒ๋ผ ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ฉฐ, ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ์ด ๊ฐ๋ฅํ๋ค.
1
2
3
4
5
6
7
8
9
import java.util.function.Function;
public class LambdaExample {
public static void main(String[] args) {
Function<Integer, Function<Integer, Integer>> add = x -> y -> x + y;
System.out.println(add.apply(2).apply(3)); // ์ถ๋ ฅ: 5
}
}
๋๋ค๋ ํจ์ํ ์ธํฐํ์ด์ค๋ฅผ ์ง์ํ๋ค๊ณ ํ๋ค. ๊ทธ๋ฌ๋ฉด ํจ์ํ ์ธํฐํ์ด์ค๊ฐ ๋ญ๊น?
ํจ์ํ ์ธํฐํ์ด์ค๋ ๋จ ํ๋์ ์ถ์ ๋ฉ์๋๋ฅผ ๊ฐ๋ ์ธํฐํ์ด์ค์ด๋ค. ์ถ์ ๋ฉ์๋๋ง ๋จ ํ๋๋ฅผ ๊ฐ๋๋ค.!!!
๊ทธ ์ธ ๋ฉ์๋๋ ์๊ด์ด ์๋ค. ๋๋ค์์ ์ด ์ธํฐํ์ด์ค์ ์ธ์คํด์ค๋ฅผ ์์ฑํ๋๋ฐ ์ฌ์ฉ๋๋ค.
Java8์์ ์ ๊ณตํ๋ ์ฃผ์ ํจ์ํ ์ธํฐํ์ด์ค๋ฅผ ์ดํด๋ณด์.. ์ด๋ป๊ฒ ์ฌ์ฉ๋๋์ง๋ ๊ฐ์ด ๋ณด์.
Runnable
์ค๋ ๋๋ฅผ ์คํํ๊ธฐ ์ํ ํจ์ํ ์ธํฐํ์ด์ค
run()
์ถ์ ๋ฉ์๋๋ฅผ ๊ฐ๊ณ , ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ์ง ์์ผ๋ฉฐ ๋ฐํ๊ฐ์ด ์๋ค.
Thread ํด๋์ค์ ์์ฑ์ ์ค ํ๋๋ก Runnable ๊ฐ์ฒด๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ์ ์ค๋ ๋์ ์คํ ์์ ์ ์ ์ํ๋๋ฐ ์ฌ์ฉ๋๋ค.
์๋์ ๊ฐ์ด ๊ตฌํํ ์ ์๋ค.
1
2
3
4
5
6
7
8
9
10
public class RunnableExample {
public static void main(String[] args) {
// Runnable ์ธํฐํ์ด์ค๋ฅผ ๋๋ค์์ผ๋ก ๊ตฌํ
Runnable task = () -> System.out.println("Task is running in a thread");
// Runnable์ ์ค๋ ๋์ ์ ๋ฌํ๊ณ ์คํ
Thread thread = new Thread(task);
thread.start();
}
}
Function<T, R>
T ํ์ ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ ๋ ฅ ๋ฐ์, R์ ๋ฆฌํดํ๋ค.
- R apply (T t)
1 2 3 4
@FunctionalInterface public interface Function<T, R> { R apply(T t); }
map ๋ฉ์๋์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋๋ค. ์คํธ๋ฆผ์ ๊ฐ ์์๋ฅผ Function์ ์ฌ์ฉํด ๋ณํํ ํ ์๋ก์ด ์คํธ๋ฆผ์ ๋ฐํํ๋ค.
- Function<? super T, ? extends R> mapper๋ ๋ณํ์ ์ํํ๋ ํจ์๋ก, ์คํธ๋ฆผ์ ๊ฐ ์์(T)๋ฅผ ๋ฐ์ ์๋ก์ด ๊ฐ(R)์ ์์ฑํ๋ค.
1
2
3
4
5
6
7
8
9
10
11
public class MapExample {
public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> squares = numbers.stream()
.map(n -> n * n)
.collect(Collectors.toList());
}
}
์ฌ๊ธฐ์ map(n -> n * n) ์์ n์ ํ์
์ด ๋ช
์๋์ง ์์์ง๋ง, ์ปดํ์ผ๋ฌ๋ numbers ๋ฆฌ์คํธ๊ฐ Integer ์ธ ๊ฒ์ ์๊ณ ์๊ธฐ ๋๋ฌธ์ n๋ Integer๋ผ๊ณ ์ถ๋ก ํ๋ค. ์ด๊ฑธ ํ์
์ถ๋ก ์ด๋ผ๊ณ ํ๋ค.
์
๋ ฅ์ ๋ฐ์์ ์ถ๋ ฅ์ผ๋ก ๋ณํํ๋ฉฐ, ์ฃผ๋ก ๋ณํ ์์
์ ์ฌ์ฉ๋๋ค.
Predicate< T >
Tํ์ ์ ๋งค๊ฐ๋ณ์๋ฅผ ์ ๋ ฅ ๋ฐ์, ์กฐ๊ฑด ๊ฒ์ฌ ํ boolean ๊ฐ์ ๋ฐํํ๋ค.
- boolean test(T t)
์ ๋ ฅ ๊ฐ์ ๋ํด boolean ๊ฐ์ ๋ฐํํ๋ฉฐ, ์ฃผ๋ก ์กฐ๊ฑด ๊ฒ์ฆ์ ์ฌ์ฉํ๋ค.
Consumer< T >
Tํ์ ์ ์ ๋ ฅ์ ๋ฐ์ ๋์์ ์ํํ ํ, ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ์ง ์๋๋ค.
- void accept(T t)
์ ๋ ฅ์ ๋ฐ์์ ๋์์ ์ํํ๋ฉฐ, ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ์ง ์๋๋ค.
Supplier< T >
๋งค๊ฐ๋ณ์ ์์ด Tํ์ ์ ๊ฐ์ ๋ฐํํ๋ ํจ์ํ ์ธํฐํ์ด์ค๋ก ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ฑฐ๋ ๊ฐ์ ์ ๊ณตํ๋ค.
- T get()
๋งค๊ฐ ๋ณ์๋ฅผ ๋ฐ์ง ์๊ณ , ๊ฐ์ ์์ฑํ๊ฑฐ๋ ์ ๊ณตํ๋ค.