1212 ~ 0101
# 1212 ~ 0101
# 1213 - ๋๋ค ์บก์ฒ๋ง(Capturing Lambda)
๊ธฐ๋ณธ์ ์ผ๋ก ๋๋ค ํํ์์ (ํ๋ผ๋ฏธํฐ) -> ๋์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ฅผ ์ง๋๋ฉฐ, ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ง ๋ณ์๋ฅผ ํ์ฉํ์ฌ ๋ฐ๋์์ ์์ ์ ์ํํ๋ค. ๋๋ค ์บก์ฒ๋ง(capturing lambda)์ด๋ ๊ฐ๋จํ ๋งํด ์ด์ฒ๋ผ ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ๋ฐ์ ๋ฐ์ดํฐ๊ฐ ์๋ "๋๋ค์ ์ธ๋ถ์์ ์ ์๋ ๋ณ์"๋ฅผ ์ฐธ์กฐํ๋ ๋ณ์๋ฅผ ๋๋ค์ ๋ด๋ถ์ ์ ์ฅํ๊ณ ์ฌ์ฉํ๋ ๋์์ ์๋ฏธํ๋ค. ์๋๋ ๊ทธ ์์ด๋ค.
void lambdaCapturing() {
int localVariable = 1000;
Runnable r = () -> System.out.println(localVariable);
}
2
3
4
5
# [ ์ ์ฝ ์กฐ๊ฑด: ์ง์ญ๋ณ์๋ final์ด์ด์ผ ํ๋ค ]
๋๋ค๋ ๊ฐ์ด ๋จ ํ ๋ฒ๋ง ํ ๋น๋๋ ์ง์ญ๋ณ์๋ง์ ์บก์ฒํ ์ ์์ผ๋ฉฐ, ๋ง์ผ ๋๋ค์์ ์บก์ฒ๋๋ ์ง์ญ๋ณ์์ ๊ฐ์ ์ฌํ ๋น๋๋ ๊ฒฝ์ฐ ์ปดํ์ผ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค. ์ฆ, ๋ช ์์ ์ผ๋ก final๋ก ์ ์ธ๋์๊ฑฐ๋, ์ค์ง์ ์ผ๋ก final์ธ ์ง์ญ๋ณ์๋ง ๋๋ค์ ๋ฐ๋์ ๋ค์ด์ฌ ์ ์๋ค๋ ๊ฒ์ด๋ค.
์ด๋ฌํ ์ ์ฝ์กฐ๊ฑด์ JVM ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ์ ๊ด๋ จ์ด ์๋ค. JVM ๋ฉ๋ชจ๋ฆฌ์์ผ๋ก ํ์ ์ ์ฅ๋๋ ์ธ์คํด์ค ๋ณ์ ๋ฑ๊ณผ๋ ๋ฌ๋ฆฌ, ์ง์ญ๋ณ์๋ ์คํ์ ์ ์ฅ๋๊ธฐ ๋๋ฌธ์ด๋ค.
์๋ฅผ ๋ค์ด '์ง์ญ๋ณ์์ ๊ฐ์ ์บก์ฒํ๋ ๋๋ค'๋ฅผ ๋ฐํํ๋ ๋ฉ์๋๋ฅผ ํ ๋ฒ ์๊ฐํด๋ณด์. ํด๋น ๋ฉ์๋์ ์คํ์ด ์ข ๋ฃ๋๋ ๊ฒฝ์ฐ, JVM์ ๋ฐํ๋๋ ๋๋ค์์ ๋ฐ๋์ ํฌํจ๋์ด ์๋ ์ง์ญ๋ณ์์ ํ ๋น์ ํด์ ํ๋ค. ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ๋๋ค๋ ์ง์ญ๋ณ์์ ๊ฐ์ ์๋ฌด ๋ฌธ์ ์์ด ์ฐธ์กฐํ์ฌ ์ฌ์ฉํ ์ ์๋ค. ์ด๋ ๋๋ค ๋ด๋ถ์์ ์ฌ์ฉ๋๋ ์ง์ญ๋ณ์๋ ์๋ณธ ์ง์ญ๋ณ์๋ฅผ ๋ณต์ ํ ๋ฐ์ดํฐ์ด๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ์ค์ ์ง์ญ๋ณ์์ ํ ๋น์ด ํด์ ๋์ด๋ ๋๋ค ๋ด๋ถ์ ๊ฐ์ ์ ์ง๋๋ ๊ฒ์ด๋ฉฐ, ๋ณต์ ํ์ ๊ฐ์ด ๋ณ๊ฒฝ๋์ง ์์์ผ ํ๋ค๋ ์ด์ ๋ก ๋จ ํ ๋ฒ๋ง ๊ฐ์ ํ ๋นํด์ผ ํ๋ค๋ ์ ์ฝ์ด ์๊ฒจ๋ ๊ฒ์ด๋ค.
void useLambda() {
Supplier<Integer> lambda = getLambda();
int actual = lambda.get();
System.out.println(actual); // 1005
}
// ์ง์ญ๋ณ์๋ฅผ ์บก์ฒํ์ฌ ์ฌ์ฉํ๋ ๋๋ค๋ฅผ ์ธ๋ถ๋ก ๋ฐํํ๋ ๋ฉ์๋
private Supplier<Integer> getLambda() {
int localVariable = 1000; // ์ง์ญ๋ณ์ localVariable
return () -> localVariable + 5; // ์์ ๋ณ์ localVariable
}
2
3
4
5
6
7
8
9
10
11
12
13
14
๊ทธ๋ฆฌ๊ณ ์ด์ฒ๋ผ ๋๋ค์ ๋ด๋ถ์์ ์ ์ฅ๋๋ ์ง์ญ๋ณ์์ ๋ณต์ ํ์ ์๋ณธ์ด ๋๋ ์ง์ญ๋ณ์์ด ์ฌ๋ผ์ ธ๋ ์์ ๋กญ๊ฒ ์กด์ฌํ ์ ์๊ธฐ ๋๋ฌธ์ ์์ ๋ณ์๋ผ๊ณ ๋ถ๋ฆฐ๋ค.
์ฌ์ค ์ง์ญ๋ณ์์ ๋ถ๋ณ์ฑ์ ๊ฐ์ ํ๋ ๊ฒ์ ๋ฑํ ๋ฌธ์ ๋ผ๊ณ ๋ณด๊ธฐ ์ด๋ ต๋ค. ๋ถ๋ณ์ฑ์ด ์ง๋ ๋ค์ํ ์ด์ ๋ ์๊ฒ ์ง๋ง, ์ธ๋ถ ๋ณ์์ ๊ฐ์ ์ง์ ์ ์ผ๋ก ๋ณํํ๋ ์ผ๋ฐ์ ์ธ ์ ์ฐจํ/๋ช ๋ นํ ํ๋ก๊ทธ๋๋ฐ ํจํด์ ์๋ฐฉํ๋ค๋ ์ ์ด ๊ฐ์ฅ ํฐ ์ด์ ์ด๋ผ๊ณ ๋ณผ ์ ์๋ค์ ์ ์ ์ฝ ์กฐ๊ฑด์ ์ด์ ์ผ๋ก ๋ณผ ์ ์๋ค.
# 1215 - Thread์ Runnable
# 1. Thread์ Runnable์ ๋ํ ์ดํด ๋ฐ ์ฌ์ฉ๋ฒ
# [ ์ฐ๋ ๋์ ์๋ฐ์ ๋ฉํฐ ์ฐ๋ ๋ ]
์ฐ๋ ๋๋ ํ๋ก๊ทธ๋จ ์คํ์ ๊ฐ์ฅ ์์ ๋จ์์ด๋ค. ์ผ๋ฐ์ ์ผ๋ก ์๋ฐ ์ ํ๋ฆฌ์ผ์ด์
์ ๋ง๋ค์ด ์คํํ๋ฉด 1๊ฐ์ ๋ฉ์ธ(main) ์ฐ๋ ๋์ ์ํด ํ๋ก๊ทธ๋จ์ด ์คํ๋๋ค. ํ์ง๋ง 1๊ฐ์ ์ฐ๋ ๋ ๋ง์ผ๋ก๋ ๋์์ ์ฌ๋ฌ ์์
์ ํ ์ ์๋ค. ๋์์ ์ฌ๋ฌ ์์
์ ์ฒ๋ฆฌํ๊ณ ์ถ๋ค๋ฉด, ๋ณ๋์ ์ฐ๋ ๋๋ฅผ ๋ง๋ค์ด ์คํ์์ผ์ค์ผ ํ๋๋ฐ, ์๋ฐ๋ ๋ฉํฐ ์ฐ๋ ๋ ๊ธฐ๋ฐ์ผ๋ก ๋์์ฑ ํ๋ก๊ทธ๋๋ฐ์ ์ง์ํ๊ธฐ ์ํ ๋ฐฉ๋ฒ๋ค์ ๊ณ์ํด์ ๋ฐ์ ์์ผ ์๋ค.
๊ทธ ์ค์์ Thread์ Runnable์ ์๋ฐ ์ด๊ธฐ๋ถํฐ ๋ฉํฐ ์ฐ๋ ๋๋ฅผ ์ํด ์ ๊ณต๋์๋ ๊ธฐ์ ์ด๋ค.
- java5 ์ด์ : Runnable๊ณผ Thread
- java5 : Callable๊ณผ Future ๋ฐ Executor, ExecutorService, Executors
- java7 : Fork/Join ๋ฐ RecursiveTask
- java9 : Flow
# [ Thread ํด๋์ค ]
Thread๋ ์ฐ๋ ๋ ์์ฑ์ ์ํด Java์์ ๋ฏธ๋ฆฌ ๊ตฌํํด๋ ํด๋์ค์ด๋ค. Thread๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ๋ฉ์๋๋ค์ ์ ๊ณตํ๋ค.
- sleep
- ํ์ฌ ์ฐ๋ ๋ ๋ฉ์ถ๊ธฐ
- ์์์ ๋์์ฃผ์ง๋ ์๊ณ , ์ ์ด๊ถ์ ๋๊ฒจ์ฃผ๋ฏ๋ก ๋ฐ๋๋ฝ์ด ๋ฐ์ํ ์ ์์
- interupt
- ๋ค๋ฅธ ์ฐ๋ ๋๋ฅผ ๊นจ์์ interruptedException์ ๋ฐ์์ํด
- Interupt๊ฐ ๋ฐ์ํ ์ฐ๋ ๋๋ ์์ธ๋ฅผ catchํ์ฌ ๋ค๋ฅธ ์์ ์ ํ ์ ์์
- join
- ๋ค๋ฅธ ์ฐ๋ ๋์ ์์ ์ด ๋๋ ๋ ๊น์ง ๊ธฐ๋ค๋ฆฌ๊ฒ ํจ
- ์ฐ๋ ๋์ ์์๋ฅผ ์ ์ดํ ๋ ์ฌ์ฉํ ์ ์์
Thread ํด๋์ค๋ก ์ฐ๋ ๋๋ฅผ ๊ตฌํํ๋ ค๋ฉด ์ด๋ฅผ ์์๋ฐ๋ ํด๋์ค๋ฅผ ๋ง๋ค๊ณ , ๋ด๋ถ์์ run ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํ๋ค. ๊ทธ๋ฆฌ๊ณ Thread์ start ๋ฉ์๋๋ฅผ ํธ์ถํ๋ฉด run ๋ฉ์๋๊ฐ ์คํ๋๋ค. ์คํ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด main ์ฐ๋ ๋๊ฐ ์๋ ๋ณ๋์ ์ฐ๋ ๋์์ ์คํ๋จ์ ํ์ธํ ์ ์๋ค.
@Test
void threadStart() {
Thread thread = new MyThread();
thread.start();
System.out.println("Hello: " + Thread.currentThread().getName());
}
static class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread: " + Thread.currentThread().getName());
}
}
// ์ถ๋ ฅ ๊ฒฐ๊ณผ
// Hello: main
// Thread: Thread-2
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
์ฌ๊ธฐ์ run์ ์ง์ ํธ์ถํ๋ ๊ฒ์ด ์๋๋ผ start๋ฅผ ํธ์ถํ๋ ๊ฒ์ ์ฃผ์ํด์ผ ํ๋ค. ์ฐ๋ฆฌ๋ ํด๋น ๋ฉ์๋์ ์คํ์ ๋ณ๋์ ์ฐ๋ ๋๋ก ํ๊ณ ์ถ์ ๊ฒ์ธ๋ฐ, run์ ์ง์ ํธ์ถํ๋ ๊ฒ์ ๋ฉ์ธ ์ฐ๋ ๋์์ ๊ฐ์ฒด์ ๋ฉ์๋๋ฅผ ํธ์ถํ๋ ๊ฒ์ ๋ถ๊ณผํ๋ค. ์ด๋ฅผ ๋ณ๋์ ์ฐ๋ ๋๋ก ์คํ์ํค๋ ค๋ฉด JVM์ ๋์์ด ํ์ํ๋ค. ๋ฐ๋ผ์ start๋ฅผ ํธ์ถํ๋ค.
public synchronized void start() {
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
์์ ์ฝ๋๋ฅผ ๋ณด๋ฉด ์ ์ ์๋ฏ์ด start๋ ํฌ๊ฒ ๋ค์๊ณผ ๊ฐ์ ๊ณผ์ ์ผ๋ก ์งํ๋๋ค.
- ์ฐ๋ ๋๊ฐ ์คํ ๊ฐ๋ฅํ์ง ๊ฒ์ฌํจ
์ฐ๋ ๋๋ New, Runnable, Waiting, Timed Waiting, Terminated ์ด 5๊ฐ์ง ์ํ๊ฐ ์๋ค. start ๊ฐ์ฅ ์ฒ์์๋ ํด๋น ์ฐ๋ ๋๊ฐ ์คํ ๊ฐ๋ฅํ ์ํ์ธ์ง(0์ธ์ง) ํ์ธํ๋ค. ๊ทธ๋ฆฌ๊ณ ๋ง์ฝ ์ฐ๋ ๋๊ฐ New(0) ์ํ๊ฐ ์๋๋ผ๋ฉด IllegalThreadStateException ์์ธ๋ฅผ ๋ฐ์์ํจ๋ค.
- ์ฐ๋ ๋๋ฅผ ์ฐ๋ ๋ ๊ทธ๋ฃน์ ์ถ๊ฐํจ
๊ทธ ๋ค์ ์ฐ๋ ๋ ๊ทธ๋ฃน์ ํด๋น ์ฐ๋ ๋๋ฅผ ์ถ๊ฐ์ํจ๋ค. ์ฌ๊ธฐ์ ์ฐ๋ ๋ ๊ทธ๋ฃน์ด๋ ์๋ก ๊ด๋ จ์๋ ์ฐ๋ ๋๋ฅผ ํ๋์ ๊ทธ๋ฃน์ผ๋ก ๋ฌถ์ด ๋ค๋ฃจ๊ธฐ ์ํ ์ฅ์น์ธ๋ฐ, ์๋ฐ์์๋ ThreadGroup ํด๋์ค๋ฅผ ์ ๊ณตํ๋ค. ์ฐ๋ ๋ ๊ทธ๋ฃน์ ํด๋น ์ฐ๋ ๋๋ฅผ ์ถ๊ฐํ๋ฉด ์ฐ๋ ๋ ๊ทธ๋ฃน์ ์คํ ์ค๋น๋ ์ฐ๋ ๋๊ฐ ์์์ ์๋ ค์ฃผ๊ณ , ๊ด๋ จ ์์ ๋ค์ด ๋ด๋ถ์ ์ผ๋ก ์งํ๋๋ค.
- ์ฐ๋ ๋๋ฅผ JVM์ด ์คํ์ํด
๊ทธ๋ฆฌ๊ณ start0 ๋ฉ์๋๋ฅผ ํธ์ถํ๋๋ฐ, ์ด๊ฒ์ native ๋ฉ์๋๋ก ์ ์ธ๋์ด ์๋ค. ์ด๊ฒ์ JVM์ ์ํด ํธ์ถ๋๋๋ฐ, ์ด๊ฒ์ด ๋ด๋ถ์ ์ผ๋ก run์ ํธ์ถํ๋ ๊ฒ์ด๋ค. ๋๋ฆฌ๊ณ ์ฐ๋ ๋์ ์ํ ์ญ์ Runnable๋ก ๋ฐ๋๊ฒ ๋๋ค. ๊ทธ๋์ start๋ ์ฌ๋ฌ ๋ฒ ํธ์ถํ๋ ๊ฒ์ด ๋ถ๊ฐ๋ฅํ๊ณ 1๋ฒ๋ง ๊ฐ๋ฅํ๋ค.
private native void start0();
# [ Runnable ์ธํฐํ์ด์ค ]
Runnable ์ธํฐํ์ด์ค๋ 1๊ฐ์ ๋ฉ์๋ ๋ง์ ๊ฐ๋ ํจ์ํ ์ธํฐํ์ด์ค์ด๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ ๋๋ค๋ก๋ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค.
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
2
3
4
5
6
์ด๊ฒ์ ์ฐ๋ ๋๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ํ ํ๋ฆฟ์ ํด๋นํ๋๋ฐ, ํด๋น ์ธํฐํ์ด์ค์ ๊ตฌํ์ฒด๋ฅผ ๋ง๋ค๊ณ Thread ๊ฐ์ฒด ์์ฑ ์์ ๋๊ฒจ์ฃผ๋ฉด ์คํ ๊ฐ๋ฅํ๋ค. ์์ ์ดํด๋ณธ Thread ํด๋์ค๋ ๋ฐ๋์ run ๋ฉ์๋๋ฅผ ๊ตฌํํด์ผ ํ๋๋ฐ, Thread ํด๋์ค๊ฐ Runnable๋ฅผ ๊ตฌํํ๊ณ ์๊ธฐ ๋๋ฌธ์ด๋ค.
public class Thread implements Runnable {
...
}
2
3
๊ธฐ์กด์ Thread๋ก ์์ฑ๋์๋ ์ฝ๋๋ฅผ Runnable๋ก ๋ณ๊ฒฝํ๋ฉด ๋ค์๊ณผ ๊ฐ๋ค. ๋ง์ฐฌ๊ฐ์ง๋ก ๋ณ๋์ ์ฐ๋ ๋์์ ์คํ๋จ์ ํ์ธํ ์ ์๋ค.
@Test
void runnable() {
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Thread: " + Thread.currentThread().getName());
}
};
Thread thread = new Thread(runnable);
thread.start();
System.out.println("Hello: " + Thread.currentThread().getName());
}
// ์ถ๋ ฅ ๊ฒฐ๊ณผ
// Hello: main
// Thread: Thread-1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2. Thread์ Runnable ๋น๊ต
# [ Threaddhk Runnable ๋น๊ต ]
Runnable์ ์ต๋ช
๊ฐ์ฒด ๋ฐ ๋๋ค๋ก ์ฌ์ฉํ ์ ์์ง๋ง, Thread๋ ๋ณ๋์ ํด๋์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๋ค๋ ์ ์์ ๋ฒ๊ฑฐ๋กญ๋ค. ๋ํ Java์์๋ ๋ค์ค์์์ด ๋ถ๊ฐ๋ฅํ๋ฏ๋ก Thread ํด๋์ค๋ฅผ ์์๋ฐ์ผ๋ฉด ๋ค๋ฅธ ํด๋์ค๋ฅผ ์์๋ฐ์ ์ ์์ด์ ์ข์ง ์๋ค. ๋ํ Thread ํด๋์ค๋ฅผ ์์๋ฐ์ผ๋ฉด ํด๋น ํด๋์ค์ ๊ตฌํ๋ ์ฝ๋๋ค์ ์ํด ๋ ๋ง์ ์์์ ํ์๋ก ํ๋ฏ๋ก Runnable์ด ์ฃผ๋ก ์ฌ์ฉ๋๋ค.
๋ฌผ๋ก Thread ๊ด๋ จ ๊ธฐ๋ฅ์ ํ์ฅ์ด ํ์ํ ๊ฒฝ์ฐ์๋ Thread ํด๋์ค๋ฅผ ์์๋ฐ์ ๊ตฌํํด์ผ ํ ๋๋ ์๋ค. ํ์ง๋ง ๊ฑฐ์ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ์๋ Runnable ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด ํด๊ฒฐ ๊ฐ๋ฅํ๋ค.
# [ Thread์ Runnable์ ๋จ์ ๋ฐ ํ๊ณ ]
- ์ง๋์น๊ฒ ์ ์์ค์ API(์ฐ๋ ๋์ ์์ฑ)์์กดํจ
- ๊ฐ์ ๋ฐํ์ด ๋ถ๊ฐ๋ฅ
- ๋งค๋ฒ ์ฐ๋ ๋ ์์ฑ๊ณผ ์ข ๋ฃํ๋ ์ค๋ฒํค๋๊ฐ ๋ฐ์
- ์ฐ๋ ๋๋ค์ ๊ด๋ฆฌ๊ฐ ์ด๋ ค์
Executor, ExecutorService, ScheduledExecutionService์ Callable, Future
# 1224 - ์๋ฐ 8 ํ์ค API์ ํจ์ํ ์ธํฐํ์ด์ค
# ์๋ฐ 8์ด ์ ๊ณตํ๋ ํจ์ํ ์ธํฐํ์ด์ค
์๋ฐ 8๋ฒ์ ๋ถํฐ ๋น๋ฒํ๊ฒ ์ฌ์ฉ๋๋ ํจ์ํ ์ธํฐํ์ด์ค๋ฅผ java.util.function
ํ์ค API ํจํค์ง๋ก ์ ๊ณตํ๋ค. ์ ๊ณต๋๋ ํจ์ํ ์ธํฐํ์ด์ค๋ ํฌ๊ฒ 5๊ฐ์ง๋ก Consumer
, Supplier
, Function
, Operator
, Predicate
์ด๋ค. ๊ฐ ์ธํฐํ์ด์ค๋ ๋ ์ฌ๋ฌ๊ฐ์ ์ธํฐํ์ด์ค๋ก ๋๋๋ค.
๋๊ฐ์ ๋งค๊ฐ๋ณ์๋ฅผ ๋ฐ๋ ์ธํฐํ์ด์ค๋ผ๋ฉด Bi
๋ผ๋ ์ ๋์ฌ, ์ ์ ํ์
์ ๋งค๊ฐ๋ณ์๋ก ์ ๋ฌ๋ฐ๋ ์ธํฐํ์ด์ค๋ผ๋ฉด Int
๋ผ๋ ์ ๋์ฌ๊ฐ ํป์ ์ค์ ํ์
์ ๋ฐํํ๋ ์ธํฐํ์ด์ค๋ผ๋ฉด AsDouble
๊ณผ ๊ฐ์ ์ ๋ฏธ์ฌ๊ฐ ๋ฌ๋ ค์๋ ๋ฑ ์ผ์ ํ ๋ค์ด๋ฐ ๊ท์น์ด ์กด์ฌํ๋ค.
# Consumer ๊ณ์ด
๋งค๊ฐ๊ฐ์ ์๊ณ ๋ฐํ๊ฐ์ ์๋ค. ๋งค๊ฐ๊ฐ์ ์ ๋ฌ๋ฐ์ ์ฌ์ฉํ๊ณ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์์ ๋ ์ฌ์ฉ๋๋ค. ์ด๋ฅผ ์๋น(Consume) ํ๋ค๊ณ ํํํ๋ค. accept
์ถ์ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
# [ ์ฉ๋ก ]
๋ํ์ ์ผ๋ก Stream ์ forEach
๋ฉ์๋์ ๋งค๊ฐ๋ณ์ ํ์
์ด Consumer
์ด๋ค
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
numbers.stream().forEach(number -> System.out.println(number));
// Consumer ์ ๋ฌ๋จ
2
3
๋งค๊ฐ๊ฐ์ผ๋ก number
๋ฅผ ๋ฐ๊ณ ๋๋ค ํํ์ ๋ด๋ถ์์ ์ฌ์ฉ๋๊ธฐ๋ง ํ ๋ฟ ์๋ฌด๊ฒ๋ ๋ฐํํ์ง ์๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.
๋ํ Map
์ forEach
๋ฉ์๋๋ BiConsumer
ํ์
์ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๋๋ค.
Map<String, Integer> map = Map.of("hudi", 25, "baby", 1);
map.forEach((name, number) -> System.out.println(name + "๋ " + number + "์ด"));
// BiConsumer ์ ๋ฌ๋จ
2
3
์์ ๊ฐ์ด ์ฒซ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ Map
์ key๋ฅผ, ๋๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ Map
์ value ๋ฅผ ์ ๋ฌ๋ฐ๋๋ค.
# Supplier ๊ณ์ด
๋งค๊ฐ๊ฐ์ ์๊ณ , ๋ฐํ๊ฐ์ ์๋ค. ์คํ ํ ํธ์ถํ ๊ณณ์ผ๋ก ๋ฐ์ดํฐ ๊ณต๊ธ(Supply) ํ๋ค. getXXX
์ถ์๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
# [ ์ฉ๋ก ]
Stream์ generate
๋ ๋งค๊ฐ๋ณ์๋ก Supplier
ํ์
์ ๋ฐ์ ํด๋น get
๋ฉ์๋์ ๋ฐํ๊ฐ์ผ๋ก ๋ฌดํํ Stream ์ ์์ฑํ๋ค.
Stream.generate(() -> "Infinite Stream!") // Supplier ์ ๋ฌ๋จ
.limit(5)
.forEach(System.out::println);
2
3
# Function ๊ณ์ด
๋งค๊ฐ๊ฐ๋ ์๊ณ , ๋ฆฌํด๊ฐ๋ ์๋ค. ์ฃผ๋ก ๋งค๊ฐ๊ฐ์ ๋ฐํ๊ฐ์ผ๋ก ๋งคํํ ๋ ์ฆ, ํ์
๋ณํ์ด ๋ชฉ์ ์ผ ๋ ์ฌ์ฉํ๋ค. applyXXX
์ถ์ ๋ฉ์๋๋ฅผ ๊ฐ๊ณ ์๋ค.
# [ ์ฉ๋ก ]
IntStream
์ mapToObj
๋ ์ ์๋ฅผ ๊ฐ์ฒด๋ก ๋งคํํ๋ ๋ฉ์๋์ด๋ค. ์ด ๋ฉ์๋๋ ์ธ์๋ก IntFunction
ํ์
์ ์ ๋ฌ๋ฐ๋๋ค.
List<Number> numbers = IntStream.rangeClosed(0, 10)
.mapToObj(number -> new Number(number)) // IntFunction ์ ๋ฌ๋จ
.collect(Collectors.toList());
2
3
# Operator ๊ณ์ด
Function๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก, ๋งค๊ฐ๊ฐ๋ ์๊ณ , ๋ฐํ๊ฐ๋ ์๋ค. ์ฃผ๋ก ๋งค๊ฐ๊ฐ์ ์ฐ์ฐ (Operation) ํ์ฌ ๊ฒฐ๊ณผ๋ฅผ ๋ฐํํ ๋ ์ฌ์ฉ๋๋ค. Function
๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก applyXXX
์ถ์ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
# [ ์ฉ๋ก ]
Stream์ ์ฌ๋ฌ ์ค๋ฒ๋ก๋๋ reduce
๋ฉ์๋ ์ค ํ๋๋ ๋งค๊ฐ๋ณ์๋ก BinaryOperator
๋ฅผ ์ ๋ฌ๋ฐ๋๋ค. ์๋๋ BinaryOperator
๋ฅผ ํ์ฉํ์ฌ ์ปฌ๋ ์
์ ๋ชจ๋ ์๋ฅผ ๋ํ๋ ์์์ด๋ค.
List<Integer> numbers = List.of(1, 2, 3, 4, 5, 6);
Integer sum = numbers.stream()
.reduce((acc, cur) -> acc + cur) // BinaryOperator ์ ๋ฌ๋จ
.get();
2
3
4
# Predicate ๊ณ์ด
๋งค๊ฐ๊ฐ์ ์๊ณ , ๋ฐํ ํ์
์ boolean ์ด๋ค. ๋งค๊ฐ๊ฐ์ ๋ฐ์ ๊ฒ์ฌํ๊ณ true/false๋ฅผ ๋ฐํํ ๋ ์ฌ์ฉ๋๋ค. test
์ถ์ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
# [ ์ฉ๋ก ]
Stream์ allMatch
๋ฉ์๋๋ ๋งค๊ฐ๋ณ์๋ก Predicate
ํ์
์ ์ ๋ฌ๋ฐ์, ์ปฌ๋ ์
์ ๋ชจ๋ ์์๊ฐ ์ฃผ์ด์ง ์กฐ๊ฑด์ ๋ชจ๋ ์ผ์นํ๋ฉด ture๋ฅผ ๋ฐํํ๋ค.
List<Integer> numbers = List.of(10, 20, 25, 15, 30, 35);
boolean allMatched = numbers.stream()
.allMatch(number -> number > 5);
2
3
Consumer, Function, Operator ๊ณ์ด์ andThen๊ณผ copose๋ผ๋ ๋ํดํธ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค. ๋ํ Predicate ๊ณ์ด์ and, or, negate ๋ผ๋ ๋ํดํธ ๋ฉ์๋, ๊ทธ๋ฆฌ๊ณ isEqual์ด๋ผ๋ ์ ์ ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์๋ค.