CHAP19 - Modern-Java-in-Action/Online-Study GitHub Wiki
์ด๋ฒ์ฅ์์ ๋ค๋ฃฐ ๋ด์ฉ๋ค
- ๊ณ ์ฐจ์ํจ์, ์ปค๋ง, ์๊ตฌ ์๋ฃ๊ตฌ์กฐ, ๊ฒ์ผ๋ฅธ ๋ฆฌ์คํธ, ํจํด ๋งค์นญ
- ์ฐธ์กฐ ํฌ๋ช ์ฑ์ ์ด์ฉํ ์บ์ฑ, ์ฝค๋น๋ค์ดํฐ
- ๊ณ ์ฐจ์ ํจ์๋, ๋ค์ ํ๋ ์ด์์ ๋์์ ์ํํ๋ ํจ์
- ํ๋ ์ด์์ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์
- ํจ์๋ฅผ ๊ฒฐ๊ณผ๋ก ๋ฐํ
- ๋ฏธ๋ถ์์
f(x)=x^2์f(x)=2x๋ก ๋ณํํ๋ ๊ฒ์ฒ๋ผ
- ๋ฏธ๋ถ์์
- ์คํธ๋ฆผ ์ฐ์ฐ์ผ๋ก ์ ๋ฌํ๋ ํจ์์ ๋ถ์์ฉ์ด ์์ด์ผ ํ๋ ๊ฒ์ฒ๋ผ
- ๊ณ ์ฐจ ํจ์์ ์ธ์๋ก ์ ๋ฌํ๋ ํจ์์๋ ๋ถ์์ฉ์ด ์์ด์ผ ํ๋ค
- ์๋๋ฉด ๋ถ์ ํํ ๊ฒฐ๊ณผ๊ฐ ๋์ค๊ฑฐ๋, ๊ฒฝ์์ํ์ ๋น ์ง ์ ์๋ค
- ์ค๋ฌด์์๋ ์ด๋ค ๋ถ์์ฉ์ ์ผ์ผํฌ์ง ์ ํํ๊ฒ ๋ฌธ์ํํด์ผ ํ๋ค
- ์ปค๋ง์ด๋, x, y ๋ ์ธ์๋ฅผ ๋ฐ๋ ํจ์ f๋ฅผ, ํ ๊ฐ ์ธ์๋ง ๋ฐ๋ gํจ์๋ก ๋์ฒด
- ์ปค๋ง ๊ธฐ๋ฒ์ ์ ์ฉํ ์์
//์ผ๋ฐ์ ์ธ ๋ณํํจ์
static double converter(double x, double f, double b){
return x * f + b;
}
//์ฌ์ฉํ ๋๋ง๋ค ๋ณํํ ๊ฐ๊ณผ ํจ๊ป ๊ธฐ์ค๊ฐ์ ์ง์ ํด์ฃผ์ด์ผ ํ๋ค
converter(36.5, 9, 32);//๋ณํํจ์ ํฉํ ๋ฆฌํจ์
static DoubleUnaryOperator curriedConverter(double f, double b){
return (double x) -> x * f + b;
}
//์ํ๋๋๋ก ํจ์๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ ์ ์๋ค.
DoubleUnaryOperator convertCtoF = curriedConverter(9.0/5, 32);
DoubleUnaryOperator convertUSDtoGBP = curriedConverter(0.6, 0);
DoubleUnaryOperator convertKmtoMi = curriedConverter(0.6214, 0);
//์ฌ์ฉํ ๋๋ ๋ณํํ ๊ฐ๋ง applyํ๋ค.
convertCtoF.applyAsDouble(1000);-
์์์ด๋, ์ ์ฅ๋ ๊ฐ์ด ๋๊ตฐ๊ฐ์ ์ํด ์ํฅ์ ๋ฐ์ง ์๋ ์ํ์ด๋ค.
- ์ธ์๋ก ์ ๋ฌ๋ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์์์ผ ํ๋ค.
- ๊ฒฐ๊ณผ๋ก ์ ๋ฌ๋ ์๋ฃ๊ตฌ์กฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์์์ผ ํ๋ค.
- ํ๋๋ฅผ final ์ ์ธํด์ ์ ์ฝ์ ๊ฑธ ์ ์๋ค.
- ํ๋๋ฅผ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ๋์ฒดํ ์๋ ์์ง๋ง, ํ๋ ๋ด๋ถ ๊ฐ์ ๋ณ๊ฒฝํ ์๋ ์๋ค๋ ์ ์ ์ฃผ์. ํ์ํ ๊ณณ์ final์ ์ ์ ํ ์ฌ์ฉํด์ผ ํ๋ค.
- ํ๋๋ฅผ final ์ ์ธํด์ ์ ์ฝ์ ๊ฑธ ์ ์๋ค.
-
๊ฒฐ๊ณผ๊ฐ์ ๋ฐํํ ๋
- ๊ธฐ์กด ์๋ฃ๊ตฌ์กฐ ์ผ๋ถ๋ฅผ ์ฐธ์กฐํ๋ ์๋ก์ด ์๋ฃ๊ตฌ์กฐ
- ๊ฐ์ด ๋น ๋ฅด๊ฒ ๋ณ๊ฒฝ๋๋ ๊ณณ
- ex) ๋ฐ์ดํฐ์์ง
- ๊ธฐ์กด ์๋ฃ๊ตฌ์กฐ ๊ฐ๋ง ๋ณต์ฌ
- ์ฐ์ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๋ ๊ณณ
- ex) ๋ฐ์ดํฐ๋ถ์
- ๊ธฐ์กด ์๋ฃ๊ตฌ์กฐ ์ผ๋ถ๋ฅผ ์ฐธ์กฐํ๋ ์๋ก์ด ์๋ฃ๊ตฌ์กฐ
- ์ฐ์ฐ๋์ค ๊ฐ๋ณ๊ฐ์ฒด๋ฅผ ๊ฐฑ์ ํ๋ ๊ฒฝ์ฐ, ๊ธฐ์กด ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ๋ ๋ค๋ฅธ ์ฐ์ฐ์์ ์ค๋ฅ๊ฐ ๋ฐ์ํ ์ ์๋ค.
- A-B-C ๋ฆฌ์คํธ๋ฅผ ์ฐธ์กฐํด์ A-C๊น์ง ๊ฐ์ค์น ํฉ์ ๊ตฌํ๋ ์ฐ์ฐ
- ์๋๋ฆฌ์ค1 : ๊ธฐ์กด ๋ฆฌ์คํธ ์ค๊ฐ์ ์๋ก์ด ๋
ธ๋๋ฅผ ์ถ๊ฐ A-B-Z-C
- ๊ธฐ์กด ๋ฆฌ์คํธ๋ฅผ ์ฐธ์กฐํ๋ ์ฐ์ฐ์ ์์ํ๋ ๊ฒฐ๊ณผ๊ฐ์ ๋ฐ์ง ๋ชปํ ์ ์๋ค.
- ์๋๋ฆฌ์ค2 : ๊ธฐ์กด ๋ฆฌ์คํธ์์ A-B๋ฅผ ์ฐธ์กฐํ๋ ์๋ก์ด Z-C ๋ฆฌ์คํธ๋ฅผ ์์ฑํ์ฌ ์ฐ์ฐ
- ๊ธฐ์กด ๋ฆฌ์คํธ๋ฅผ ์ฐธ์กฐํ๋ ์ฐ์ฐ๋ ์์ ๊ฒฐ๊ณผ๊ฐ์ ์ป์ ์ ์๋ค.
- ์๋๋ฆฌ์ค1 : ๊ธฐ์กด ๋ฆฌ์คํธ ์ค๊ฐ์ ์๋ก์ด ๋
ธ๋๋ฅผ ์ถ๊ฐ A-B-Z-C

- ์ด๋ฒ ์ฅ์์ ์์๋ณผ ๊ฒ๋ค
- ์คํธ๋ฆผ์ ํ ๋ฒ๋ง ์๋นํ ์ ์๋ค.
- ์คํธ๋ฆผ์ ์ฌ๊ท์ ์ผ๋ก ์ ์ํ ์ ์๋ค.
-
๊ธฐ์กด ์๊ณ ๋ฆฌ์ฆ
- ํ๋ณด ์ n์ 2~sqrt(n)์ผ๋ก ๋๋์ด ๋จ์ด์ง๋์ง ํ์ธ
-
์๋ก์ด ์๊ณ ๋ฆฌ์ฆ
- 1๋จ๊ณ ์คํธ๋ฆผ ์ซ์ ์ป๊ธฐ : 2๋ถํฐ ์์ํ๋ ๋ฌดํ ์ซ์ ์คํธ๋ฆผ
- 2๋จ๊ณ ๋จธ๋ฆฌ ํ๋ : ์ฒซ๋ฒ์งธ ์์๋ฅผ ํ๋
obj.findFirst() - 3๋จ๊ณ ๊ผฌ๋ฆฌ ํํฐ๋ง : ๊ผฌ๋ฆฌ๋ฅผ ํ๋
obj.skip(1), ํํฐ๋ง ์งํobj.filter(n->n%head!=0) - 4๋จ๊ณ ์ฌ๊ท์ ์ผ๋ก ์์ ์คํธ๋ฆผ ์์ฑ
-
์คํํ๋ฉด ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ค! ์๋ํ๋ฉด..
- ์คํธ๋ฆผ์ ํ๋ฒ๋ง ์๋น๋ ์ ์๋ค.
- head()์์ findFirst()๋ก ์๋น๋๊ณ
- tail()์์ skip()์ ํธ์ถํ๋ ์ค๋ฅ๊ฐ ๋ฐ์ํ ๊ฒ
- ์คํธ๋ฆผ์ '์ฌ๊ท์ ์ ์๋ฅผ ํ์ฉํ์ง ์๋๋ค.'
- ๋์ ์ค์ ๋ก ํ์ํ ๋ ์คํธ๋ฆผ์ '๊ฒ์ผ๋ฅด๊ฒ ํ๊ฐ'ํ๋ฉด ์ ์๊ณ ๋ฆฌ์ฆ๋๋ก ์๋์ํฌ ์ ์๋ค.
- ์ค์นผ๋ผ์์๋
#::์ฐ์ฐ์๋ฅผ ์ฌ์ฉํ๋ค. - ์์ ๋ฐฐ์ด ๊ฒ์ฒ๋ผ
()->something์ํ๋ผ์ด์ด๋ก ๊ฐ์ธ๋ ๋๊ฒ ๋ค.
- ์ค์นผ๋ผ์์๋
- ๋์ ์ค์ ๋ก ํ์ํ ๋ ์คํธ๋ฆผ์ '๊ฒ์ผ๋ฅด๊ฒ ํ๊ฐ'ํ๋ฉด ์ ์๊ณ ๋ฆฌ์ฆ๋๋ก ์๋์ํฌ ์ ์๋ค.
- ์คํธ๋ฆผ์ ํ๋ฒ๋ง ์๋น๋ ์ ์๋ค.
Exception in thread "main" java.lang.IllegalStateException: stream has already been operated upon or closed
at java.base/java.util.stream.AbstractPipeline.<init>(AbstractPipeline.java:203)
at java.base/java.util.stream.IntPipeline.<init>(IntPipeline.java:91)
at java.base/java.util.stream.IntPipeline$StatefulOp.<init>(IntPipeline.java:655)
at java.base/java.util.stream.SliceOps$2.<init>(SliceOps.java:231)
at java.base/java.util.stream.SliceOps.makeInt(SliceOps.java:231)
at java.base/java.util.stream.IntPipeline.skip(IntPipeline.java:410)
at CHAPTER19.PrimeNumber.tail(Chapter19Main.java:23)
at CHAPTER19.PrimeNumber.primes(Chapter19Main.java:30)
at CHAPTER19.Chapter19Main.main(Chapter19Main.java:7)package CHAPTER19;
import java.util.stream.IntStream;
public class Chapter19Main {
public static void main(String[] args){
PrimeNumber.primes(PrimeNumber.numbers()).forEach(System.out::println);
}
}
class PrimeNumber{
static IntStream numbers(){
return IntStream.iterate(2, n -> n + 1);
}
static int head(IntStream numbers){
return numbers.findFirst().getAsInt();
}
static IntStream tail(IntStream numbers){
return numbers.skip(1);
}
static IntStream primes(IntStream numbers){
int head = head(numbers);
return IntStream.concat(
IntStream.of(head),
primes(tail(numbers).filter(n->n%head!=0))
);
}
}- ๊ฒ์ผ๋ฅธ ๋ฆฌ์คํธ
- tail์ void -> T ์ํ๋ผ์ด์ด๋ก ๋์ฒด, tail์ ํธ์ถํ์ ๋ ํ๊ฐํจ
- ์์ ํ๋ณ๋ ํ๋ฆฌ๋์ผ์ดํธ๋ก, ํธ์ถํ์ ๋ ํ๊ฐํจ
- ๊ผฌ๋ฆฌํธ์ถ ์ฌ๊ท๊ฐ ์ง์๋์ง ์๊ธฐ์, ์๋ ์์ ์ฝ๋๋ ์คํ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ๋ค
- ๋ก์ง์ ์ดํดํ๋ ๋ฐ ์ด๋ ค์ ๋ค.
- ๋๋ฒ์งธ ์ฝ๋์ ์์์ ์ printall
- tail์ ์ฌ๊ท์ ์ผ๋ก ํ๊ฐํด primes์ ์ธ์๋ก ๋๊ฒจ ์์๊ฐ ์๋ ์๋ฅผ ๊ฑธ๋ฌ๋ธ๋ค
- ํ๊ฐํ tail์ด head๋ก filterํด์ ๋๋์ด๋จ์ด์ง์ง ์์ผ๋ฉด
-
์์์ด๋ฏ๋ก ์๋ก์ด ์ํ๋ผ์ด์ด๋ฅผ ์ ๋ฌํ๊ณ ์ข ๋ฃํ๋ค
- โฎ ๋ค์ primes๋ก ๋์๊ฐ ์คํ์ค๋ฒํ๋ก๊ฐ ๋ ๋๊น์ง ๋ฐ๋ณตํ๋ค
-
์์๊ฐ ์๋๋ฏ๋ก tail์ ๋ค์ ํ๊ฐํ๊ณ filter๋ฅผ ์ฌ๊ทํธ์ถํ๋ค
-
- ํ๊ฐํ tail์ด head๋ก filterํด์ ๋๋์ด๋จ์ด์ง์ง ์์ผ๋ฉด
package CHAPTER19;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class MyLinkedListMain{
public static void main(String args[]){
/* ๊ฒ์ผ๋ฅด๊ฒ ์ฌ๊ท์ ์ผ๋ก ๋์ด๋๋ ์ซ์ ๋ฆฌ์คํธ */
System.out.println("1. ===========================");
MyLinkedList<Integer> numbers = from(2);
int two = primes(numbers).head();
System.out.println(two);
int three = primes(numbers).tail().head();
System.out.println(three);
int five = primes(numbers).tail().tail().head();
System.out.println(five);
/* ๊ณ์ ์ํํ๋ฉด ์คํ์ค๋ฒํ๋ก์ฐ๊ฐ ๋ฐ์ํ๋ค */
System.out.println("2. ===========================");
try{
printAll(primes(from(2)));
} catch(StackOverflowError e){
//e.printStackTrace();
System.out.println("stack overflow");
} catch(IllegalStateException e){
System.out.println("BREAK");
}
}
public static MyLinkedList<Integer> primes(MyLinkedList<Integer> numbers){
return new MyLinkedList<Integer>(
numbers.head(),
()->primes(
numbers.tail()
.filter(n->{
System.out.print("filter "+n+" by "+numbers.head()+"/ ");
return (n%numbers.head()!=0);
}
)
));
}
public static MyLinkedList<Integer> from(int n){
System.out.print("from@"+n+"/ ");
return new MyLinkedList<Integer>(n, ()->from(n+1));
}
public static void printAll(MyLinkedList<Integer> list){
if(list.isEmpty()) return;
System.out.println(list.head());
printAll(primes(list.tail()));
}
}
class MyLinkedList<T> implements MyList<T> {
public static int cnt = 0;
private final T head;
private final Supplier<MyLinkedList<T>> tail;
public MyLinkedList(T head, Supplier<MyLinkedList<T>> tail){
this.head = head;
this.tail = tail;
}
@Override
public T head() {
return head;
}
@Override
public MyLinkedList<T> tail() {
//์ ํ์ ๋
if((int)head>=50) throw new IllegalStateException("BREAK");
return tail.get();
}
@Override
public boolean isEmpty(){
return false;
}
public MyLinkedList<T> filter(Predicate<T> p){
return isEmpty() ?
this :
p.test(head()) ? //ํ๊ฐํ tail์ด head๋ก filterํด์ ๋๋์ด๋จ์ด์ง์ง ์์ผ๋ฉด
new MyLinkedList<T>(head(), ()->tail().filter(p)) : //์ฐธ์ด๋ฉด ์์์ด๋ฏ๋ก, ์๋ก์ด ์ํ๋ผ์ด์ด๋ฅผ ์ ๋ฌํ๊ณ ์ข
๋ฃ
tail().filter(p); //๊ฑฐ์ง์ด๋ฉด ์์๊ฐ ์๋๋ฏ๋ก, tail์ ๋ค์ ํ๊ฐํ๊ณ filter๋ฅผ ์ฌ๊ทํธ์ถ
}
}
interface MyList<T>{
T head();
MyList<T> tail();
default boolean isEmpty(){
return true;
}
}
class Empty<T> implements MyList<T>{
@Override
public T head(){
throw new UnsupportedOperationException();
}
@Override
public MyList<T> tail(){
throw new UnsupportedOperationException();
}
}-
๊ทธ๋ฐ๋ฐ ์ฌ์ค ์ ์๊ณ ๋ฆฌ์ฆ์ ์๋ผํ ์คํ ๋ค์ค์ ์ฒด๊ฐ ์๋๋ค. ๋ ํจ์จ์ ์ธ ์๊ณ ๋ฆฌ์ฆ์ด๋ค.
-
์๋ผํ ์คํ ๋ค์ค์ ์ฒด : ์์๋ฅผ ์ฐพ๊ณ , ๊ทธ ์์์ ๋ฐฐ์๋ฅผ ๋ชฉ๋ก์์ ๋ชจ๋ ์ง์ด๋ค. ๋ฐ๋ณตํ๋ค.
- 2 -> 4, 6, 8, 10์ด ๋ชจ๋ ์์ด์ง๋ค.
-
19.3์ ์ ์๊ณ ๋ฆฌ์ฆ : n++๋ณด๋ค ์์ ์์๋ก n์ ๋๋ ๋ณธ๋ค. ๋๋ ์ง์ง ์์ผ๋ฉด ์์๋ก ํ๋จํ๊ณ ์์ ๋ชฉ๋ก์ ์ถ๊ฐํ๋ค. ๋ฐ๋ณตํ๋ค.
- 2, 3, 4 ์์๋๋ก ํ๊ฐํ๊ธฐ ๋๋ฌธ์ ์ต์ ํ๋์ด ์์ง ์๋ค.
- ๊ทธ๋ผ์๋ ๋ถ๊ตฌํ๊ณ ๋ฌดํํ ์์ ๋ํ์ฌ ์ฐ์ฐ์ ๊ณ์ํ ์ ์๋ค๋ ์ฅ์ ์ด ์๋ค.
-
-
๋ค์๊ณผ ๊ฐ์ ์ํฉ์ ์๋ฐ์์๋ ์ด๋ป๊ฒ ํํํ ์ ์์๊น?
-
f(0) = 1,f(n) = n * f(n-1) - ๋ค์ด๋๋ฏน ์๊ณ ๋ฆฌ์ฆ ๋ฌธ์ ํ์ด๋ฅผ ํ ๋, ์ด๋ฐ ๊ฒฝ์ฐ
dp[0]=1๋if(n==0) return 1;๋ฑ ์ง์ ์ฒ๋ฆฌํด์ค์ผํ๋ค. ๋ค๋ฅธ ๋ฐฉ๋ฒ์ ์์๊น?
-
-
๋ณด๋ค ๊ตฌ์ฒด์ ์ธ ์๋ฅผ ๋ค๋ฉด
-
new BiOperation("+", new Number(5), new Number(0))๋ฅผnew Number(5)๋ก ๋จ์ํํ๋ ค๋ฉด ์ด๋ป๊ฒ ํด์ผํ ๊น? - ๋ฉ์๋ ์ธ์์ ํ์๊ณผ ๊ฐ์ผ๋ก, ๋ง์ ๊ทธ๋ฆฌ๊ณ ๋ํ๋ ์ซ์๊ฐ 0์ธ์ง ํ์ธํ๋ค.
- ๋ฉ์๋ ์๊ทธ๋์ฒ๋ฅผ ์ง์ ๊ฒ์ฌํ ์๋ ์์ผ๋ฏ๋ก, ์ธ์๋ฅผ ๊ฐ๊ฐ ๊ฒ์ฌํ๋ค.
-
Expression simplyfyExpression(Expression expr){
if(expr instanceof BiOperation
&& ((BiOperation)expr).opname.equals("+")
&& ((BiOperation)expr).right intanceof Number
&& ((Number)((BiOperation)expr).right).value.equals(0))
return (BiOperation)expr.left;
}- ๋ฐฉ๋ฌธ์ ๋์์ธ ํจํด์ผ๋ก ์ฒ๋ฆฌ๋ก์ง์ '์์'ํ ์ ์๋ค.
- ๋ฐฉ๋ฌธ์ ๋์์ธ ํจํด์ด๋?
- ์ด๋ค ์ ์ด ๋์์ง๊ฑธ๊น?
- ์ฒ๋ฆฌ๋ก์ง์ ์์
- ๊ธฐ์กด ๊ฐ์ฒด์ ๋ฉค๋ฒ๋ฅผ ์์ ํ์ง ์๊ณ ์ฐ์ฐ์ ์ถ๊ฐ
- ์ด๋์ ํด๋น ๊ฐ์ฒด๋ฅผ ์ฒ๋ฆฌํ๋์ง ๋ถ๋ช ํ๊ฒ ํํ
- ์ฒ๋ฆฌ๋ก์ง์ ์์
public class SimplifyVisitor{
public Expr visit(BinOp e){
if("+".equals(e.opname) && e.right.instanceof Number && ...){
return e.left;
}
return e;
}
}
class BinOp extends Expr{
public Expr accept(SimplifyExprVisitor v){
return v.visit(this);
}
}-
๋ฐฉ๋ฌธ์ ๋์์ธ ํจํด์
- ์๋ฃ๊ตฌ์กฐ์ N:N ์ฒ๋ฆฌ๋ก์ง์ ๋ถ๋ฆฌํด์ผํ ๊ฒฝ์ฐ, ์ด๋ฅผํ ๋ฉด ์ฒ๋ฆฌ๋ก์ง์ด ์์ฃผ ๋ฐ๋๋ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ค.
- ๊ณ ๊ฐ์ด ์์ ์ '๋ฐฉ๋ฌธ(์ ๊ฒ/๋ฉํ/ํ๋ถ/๊ตํ ๋ฑ)'ํ๋ค๋ ํ๋ก๊ทธ๋จ์์,
- ๊ธฐ์กด: ๊ณ ๊ฐ ๊ฐ์ฒด visit์ ์์ ์ ์ ๋ฌํ์ฌ ์ฒ๋ฆฌ
- ํจํด: ์์ ๊ฐ์ฒด accept์ ๊ณ ๊ฐ์ ์ ๋ฌํ๊ณ , ๋ด๋ถ์์ ๊ณ ๊ฐ๊ฐ์ฒด visit ์ฒ๋ฆฌ
- ๋จ์
- ์๋ก์ด ์์ ๋์์ด ์ถ๊ฐ๋ ๋๋ง๋ค, ์์ ์ฃผ์ฒด์ ๋ก์ง์ ์ถ๊ฐํด์ผ ํ๋ค.
- ๋ ๊ฐ์ฒด๊ฐ ์๋ก ์์กดํ๋ฏ๋ก ๊ฒฐํฉ๋๊ฐ ๋์์ง๋ค.
- ์ฐธ์กฐ: [แแ ตแแ กแแ ตแซ แแ ขแแ ฅแซ 15แแ งแซ] ํ๋ ํจํด, ๋ฐฉ๋ฌธ์ (Visitor) (tistory.com), ๋ฐฉ๋ฌธ์ ํจํด(Visitor Pattern) -.. : ๋ค์ด๋ฒ๋ธ๋ก๊ทธ (naver.com)
-
์ ์ฝ๋์ ๊ฒฝ์ฐ ์ด๋ค ์ ์ด ๋์์ง๊ฑธ๊น...
- ์ฅ์
- ์ดํญ์ฐ์ฐ ๊ฐ์ฒด ์๊ธฐ์์ ์ ์ฒ๋ฆฌํ๋ ๋ก์ง์ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ์์ํ๋ค.
- ๋จ์
- ์ดํญ์ฐ์ฐ์ด ์๋๋ผ ์ผํญ์ฐ์ฐ์ ๊ฐ๋ตํ๊ฒ ํํํ๋ ค๋ฉด, visit์ ์๋ก ์์ฑํด์ผํ๋ค. ํน์ ์ดํญ์ฐ์ฐ ๋ฉค๋ฒ๊ฐ ๋ฐ๋๋ฉด visit์ ์๋ก ์์ฑํด์ผ ํ๋ค.
- ์ฐ์ฐ ๊ฐ์ฒด์ ๊ฐ๋ตํ๊ฒ ํ๋ ๊ฐ์ฒด๊ฐ ์๋ก ๋ง์ด ์์กดํ๊ฒ ๋๋ค.
- ๋ด ์๊ฐ
-
์ฃผ์ฒด.๋ฉ์๋(๋์)์๋์.๋ฉ์๋(์ฃผ์ฒด)์ ๊ฒฐ๊ณผ๋ ๊ฐ๋ค. - ๊ทธ๋ฌ๋
๋์.๋ฉ์๋(์ฃผ์ฒด)ํจํด์, ๋์์ ์ฒ๋ฆฌํ ๋ก์ง์ ์ฃผ์ฒด๋ก ์์ํ๋ค๋ ์ ์ ๋ ๋ถ๋ช ํ๊ฒ ํํํ ์ ์๋ค. - ์์ ๊ฐ์ ํจํด์ ๊ณ์ํด์ ์ด์ด์ ์ฌ์ฉํ๋ฉด, ๊ธฐ์กด ํด๋์ค ๋ฉค๋ฒ๋ ์ ์งํ์ฑ๋ก ์๋ก์ด ์ฐ์ฐ์ ์ถ๊ฐํ ์ ์๋ค.
-
- ์ฅ์
- ๋ง์ฝ, switch/case์์ ๋ฉ์๋ ์๊ทธ๋์ฒ๋ฅผ ๊ธฐ์ค์ผ๋ก ๊ตฌ๋ณํ ์ ์๋ค๋ฉด ๋ ๊ฐ๋จํ ํํํ ์ ์์ ๊ฒ์ด๋ค.
- ์ค์นผ๋ผ์์๋ ์๋์ ๊ฐ์ ํจํด๋งค์นญ์ ์ง์ํ๋ค.
- ์๋ฐ๋ ์ง์์ํ๋ค.
- ๊ธฐ๋ณธํ, ์ด๊ฑฐํ, ์ผ๋ถ ๊ธฐ๋ณธํ ๋ํผํด๋์ค, ๋ฌธ์์ด ๋ฑ์ ์ฌ์ฉํ ์ ์๋ค.
def simplifyExpression(expr: Expr): Expr = expr match{
case BinOp("+", e, Number(0)) => e
case BinOp("*", e, Number(1)) => e
case BinOp("/", e, Number(1)) => e
case _ => expr
}- ๊ทธ๋ฌ๋ ์ฐ๋ฆฌ์๊ฒ ๋๋ค๊ฐ ์๋ค. ๋๋ค๋ก ํจํด๋งค์นญ์ ํ๋ด๋ด๋ณด์.
- ์ค์นผ๋ผ์ ๊ฒฝ์ฐ ๋ค์ค switch๋ฌธ์ด๋ผ ํ ์ ์๋ค.
- ๋จผ์ BinOp ๋ฉ์๋์ธ์ง ํ์ธํ๊ณ
- ์ธ์๋ก ์ ๋ฌ๋ ๊ฒ์ด ๋ฌด์์ธ์ง ํ์ธํ๋ค
- ์๋ฐ์ ๊ฒฝ์ฐ ์๋์ ๊ฐ์ ์ฝ๋๋ก ๋ณด๋ค ๋ฒ์ฉ์ ์ธ switch๋ฅผ ๋ง๋ค ์ ์๋ค.
- ์ค์นผ๋ผ์ ๊ฒฝ์ฐ ๋ค์ค switch๋ฌธ์ด๋ผ ํ ์ ์๋ค.
//์ฌ์ฉ
myIf(n%2==0, ()->42์ต*42์ต, ()->42์ต);
myIf(do(something).IsSucceed(), ()->successHandler, ()->failHandler);
//๊ตฌํ
static <T> T myIf(boolean b, Supplier<T> truecase, Supplier<T> falsecase){
return b ? truecase.get() : falsecase.get();
}์ฐ์ฐ์ ๊ฐ๋จํํ๋ ๊ธฐ์กด์์ ๋ ์๋์ ๊ฐ์ด ๋ฐ๊ฟ ์ ์๋ค.
- ๊ทธ๋ฌ๋ฉด ์ด๋ค ์ ์ด ๋ ๋์์ง๋?
- ์ถ์ํ: ์กฐ๊ฑด๋ฌธ์ ๋ฉ์๋ ๋ด๋ถ๋ก ๋ชจ๋ ๊ฐ์ท๋ค.
- ๋คํ์ฑ: TriFunction, ๊ทธ๋ฆฌ๊ณ ์ํ๋ผ์ด์ด๋ฅผ ๋ค์ ์ ์ํ๋ฉด, ์ซ์๋ฟ ์๋๋ผ ๋ค๋ฅธ ํ์์๋ ์ฌ์ฉํ ์ ์๋ค.
- ์ด๋ฅผํ ๋ฉด ์ํ๋ผ์ด์ด๋ฅผ ๊ฐ์ฒด ๋ด๋ถ ๋ฌธ์์ด ๊ฐ์ ์ฝ๋ ๊ฒ์ผ๋ก ๋ฐ๊พธ๊ณ
- TriFunction์์๋ ๋ฌธ์์ด ๋ง์ ์์ ๋ค์ ๋น ๋ฌธ์์ด์ด ์ค๋์ง ํ์ธํ๊ณ , ์ผ์ชฝ ์ธ์๋ง ๋ฐํํ๋ค๋ ์ง
- ์ฝ๋์ ์์ ๋ณํจ์๋ค.
//์ฌ์ฉ
simplify(new BiOperation("+", new Number(5), new Number(0)));
//๊ตฌํ
interface TriFunction<S, T, U, R>{
R apply(S s, T t, U u);
}
static <T> T patternMatchExpr(
Expr e,
TriFunction<String, Expr, Expr, T> binopcase,
Function<Integer, T> numcase,
Supplier<T> defaultcase){
return
(e instanceof BinOp) ?
binopcase.apply(((BinOp)e).opname, ((BinOp)e).left,
((BinOp)e).right) :
(e instanceof Number) ?
numcase.apply(((Number)e).val) :
defaultcase.get();
}
public static Expr simplify(Expr e){
TriFunction<String, Expr, Expr, Expr> binopcase =
(opname, left, right) -> {
if("+".equals(opname)){
if(left instanceof Number && ((Number)left).val==0){
return right;
}
if(right instanceof Number && ((Number)right).val==0){
return left;
}
}
if("*".equals(opname)){
//do something;
}
return new BinOp(opname, left, right);
};
Function<Integer, Expr> numcase = val -> new Number(val);
Supplier<Expr> defaultcase = () -> new Number(0);
return patternMatchExpr(e, binopcase, numcase, defaultcase);
}-
- ๋ถ์ํจ๊ณผ/๋ถ์์ฉ : ํจ์๋ด ์คํ์ผ๋ก ํจ์ ์ธ๋ถ๊ฐ ์ํฅ์ ๋ฐ๋๊ฒ
-
์ฐธ์กฐํฌ๋ช
์ฑ : ํจ์/๋ฉ์๋๊ฐ ํจ์ ์ธ๋ถ์ ์ํฅ์ ๋ฐ์ง ์๋ ๊ฒ
- ํจ์์ ๊ฒฐ๊ณผ๋ ์ ๋ ฅ ํ๋ผ๋ฏธํฐ์ ์์กดํ๊ณ , ํจ์ ์ธ๋ถ(๋ฐ์ดํฐ๋ฒ ์ด์ค ๋ฑ)์ ์์กดํ์ง ์๋ ๊ฒ.
- ํน์ง
- ์๊ธฐ์ถฉ์กฑ์ : ํจ์ ์ธ๋ถ์ ์์กดํ๋ ์ฝ๋๊ฐ ์๊ณ , ํจ์ ์ฌ์ฉ์ ์ ์ฅ์์๋ ์ ํจํ ๋งค๊ฐ๋ณ์๋ง ์ ๋ฌํ๋ฉด ๋๋ค.
- ๊ฒฐ์ ๋ก ์ : ๋์ผํ ๋งค๊ฐ๋ณ์์ ๋ํด์๋ ํญ์ ๋์ผํ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.
- ์์ธ๋ฅผ ๋์ง์ง ์๋๋ค. ์์ธ๋ ๋ฒ๊ทธ์ด๊ณ , ํจ์ ์ฌ์ฉ์๊ฐ ๋ค๋ฃฐ ์ ์๋ ๊ฒ์ผ๋ก ๋ณด์ง ์๋๋ค.
- ๋ค๋ฅธ ์ฝ๋๊ฐ ์๊ธฐ์น ์๊ฒ ์คํจํ๋ ์กฐ๊ฑด์ ๋ง๋ค์ง ์๋๋ค. ๋งค๊ฐ๋ณ์์ ๊ฐ์ ๋ณ๊ฒฝํ๊ฑฐ๋ ํจ์ ์ธ๋ถ์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ์ง ์๋๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค, ํ์ผ์์คํ , ๋คํธ์ํฌ ๋ฑ ์ธ๋ถ ์์ธ์ผ๋ก ๋์์ด ๋ฉ์ถ์ง ์๋๋ค.
-
ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์ผ๋ก ์ป์ ์ ์๋ ์ด๋
- ๊ฒฐ์ ๋ก ์ ์ด๋ฏ๋ก ํ๋ก๊ทธ๋จ์ ๊ด๋ฒ์ํ๊ฒ ํ ์คํธํ๋ ๋์ ํด๋น ํจ์๊ฐ ์ฌ๋ฐ๋ฅด๊ฒ ๋์ํ๋์ง๋ง ํ์ธํ๋ฉด ์ค๋ฅ์ ์์ธ์ ์ฐพ์ ์ ์๋ค.
- ๋ถ์ํจ๊ณผ๊ฐ ์์ผ๋ฏ๋ก ํ ์คํธ์ฉ ๊ฐ์ง ๊ฐ์ฒด๋ฅผ ๋ง๋ค ํ์๊ฐ ์๋ค. (ํ ์คํธ ์ค์๋ ๋์ ๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ์ง ์์ผ๋ฏ๋ก)
- ๋ถ์ํจ๊ณผ๊ฐ ์๊ณ , ์ธ๋ถ ์์ธ์์ ์์ ๋กญ๊ณ , ์์ธ๊ฐ ์๊ณ , ๊ฐ์ ๋ณ๊ฒฝ์ด ์ผ์ด๋์ง ์๊ณ , ๋์์ฑ ๋ฌธ์ ์์ ์์ ๋ก์ฐ๋ฏ๋ก, ํจ์๋ฅผ ์กฐํฉํด์ ์ฌ์ฉํ๊ธฐ๊ฐ ๋ ์ฝ๋ค.
-
์ฝค๋น๋ค์ดํฐ: ๋ ๊ฐ ์ด์ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์ ๋ค๋ฅธ ํจ์๋ฅผ ๋ฐํํ๋ ๋ฉ์๋/ํจ์
- ํธ๋ฆฌ ํ์์ ํ ํด๋ก์ง๋ฅผ ๊ฐ๋ ๋คํธ์ํฌ์์ ํน์ ๋ฒ์ ๋ด ๋
ธ๋ ์๋ฅผ ๊ณ์ฐํ๋ ๋ถ์์ฉ ์๋ ๋ฉ์๋
- ๋ฐ๋ณตํด๋ ๋คํธ์ํฌ์ ๋ณ๊ฒฝ์ ๊ฐ์ง ์์ง๋ง, ์ฐ์ฐ ๋น์ฉ์ด ๋น์ธ๋ค.
- ์ด๋ฏธ ์ฐ์ฐํ ๋ฒ์๋ฅผ ํด์๋งต ๋ฑ์ ๋ฃ์ด ์ฐธ์กฐํ๋ฉด ์ฐ์ฐ์ ์ค์ผ ์ ์๋ค.
- ๋ค๋ง, ๋ชจ๋ ๊ณต์ ํ๋ ๊ฐ๋ณ๊ฐ์ฒด๋ฅผ ์์ ํ๋ ๊ฒ์ด๋ฏ๋ก ์์ ํ 'ํจ์ํ'์ด๋ผ๊ณ ํ๊ธฐ๋ ์ด๋ ต๋ค.
- ๋ํ ํด์๋งต์ ์ค๋ ๋ ์ธ์ดํํ์ง ์๋ ์๋ฃ๊ตฌ์กฐ์ด๋ค.
final Map<Range, Integer> numberOfNodes = new HashMap<>();
//์ง์ ๊ตฌํ
Integer computeNumberOfNodesUsingCache(Range range){
Integer result = numberOfNodes.get(range);
if(result!=null) return result;
result = computeNumberOfNodes(range);
numberOfNodes.put(range, result);
return result;
}
//computeIfAbsent์ฌ์ฉ
Integer computeNumberOfNodesUsingCache(Range range){
return numberOfNodes.computeIfAbsent(range, this::computeNumberOfNodesUsingCache);
}- ํจ์ํ ํ๋ก๊ทธ๋๋ฐ์์ ์ธ์๊ฐ ๊ฐ๋ค๋ฉด ๊ฒฐ๊ณผ๋ ๊ฐ์์ผ ํ๋ค.
- 19.2.3์ ์ ์ด์งํธ๋ฆฌ ์์ ์์๋ ์ผ๋ถ ๋
ธ๋๋ฅผ ์๋ก ์์ฑํด์ ๋ฐํํ๋ค. ์ด ๋ฉ์๋๋ ์ฐธ์กฐํฌ๋ช
์ฑ(=์ธ์๊ฐ ๊ฐ๋ค๋ฉด ๊ฒฐ๊ณผ๋ ๊ฐ๋ค)์ ๊ฐ์ง๊น?
- ๋งค๋ฒ ์๋ก์ด ๊ฐ์ฒด๋ฅผ ๋ฐํํ๋ฏ๋ก ์ฐธ์กฐํฌ๋ช ํ์ง ์๋ค.
- ๊ธฐ์กด๊ฐ์ฒด๋ฅผ ๋ณ๊ฒฝํ์ง ์์๊ณ ๊ฐ์ ๊ฐ์ ๊ฐ์ง๋ฏ๋ก ์ฐธ์กฐํฌ๋ช ํ๋ค.
- ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ f์ ์ฐ์์ ์ผ๋ก n๋ฒ ์ ์ฉํ๋ ๋ฃจํ ์ฐ์ฐ์ ์ด๋ ๊ฒ ๊ตฌํํ ์ ์๋ค.
repeat(3, (Integer x) -> 2*x);
static <A> Function<A,A> repeat(int n, Function<A,A> f){
return n==0 ? x->x : compose(f, repeat(n-1, f));
}-
ํจ์๋ฅผ ์กฐํฉํด์ ์ฌ์ฉํ ์ ์๋ค. ๋ชจ๋ํํ๊ณ ์ฌ์ฌ์ฉํ๊ธฐ ํธํ๋ค.
-
์ผ๊ธํจ์๋ ์ธ์๋ก ์ ๋ฌํ๊ฑฐ๋, ๊ฒฐ๊ณผ๋ก ๋ฐํํ๊ฑฐ๋, ์๋ฃ๊ตฌ์กฐ์ ์ ์ฅํ ์ ์๋ค.
-
๊ณ ์ฐจํจ์๋ ํ๋ ์ด์์ ํจ์๋ฅผ ์ธ์๋ก ๋ฐ์ ๋ค๋ฅธ ํจ์๋ฅผ ๋ฐํํ๋ ํจ์๋ค.
-
์ปค๋ง์ ํจ์๋ฅผ ๋ชจ๋ํํ๊ณ ์ฝ๋๋ฅผ ์ฌ์ฌ์ฉํ ์ ์๋๋ก ์ง์ํ๋ค.
-
์ฝค๋น๋ค์ดํฐ๋ ๋ ์ด์์ ํจ์๋ ์๋ฃ๊ตฌ์กฐ๋ฅผ ์กฐํฉํ๋ ํจ์ํ ๊ฐ๋ ์ด๋ค.
-
-
๋ถ์์ฉ์ด ์๋ ํจ์๋ฅผ ์ฌ์ฉํ๋ฉด ์๋ฃ๊ตฌ์กฐ๊ฐ ๋ณ๊ฒฝ๋ ๊ฑฑ์ ์ ํ์ง ์์๋ ๋๋ค.
- ์์ ์๋ฃ๊ตฌ์กฐ๋ ๊ธฐ์กด ๋ฒ์ ์ ์์ ์ ๋ณด์กดํ๋ค.
-
์ํ๋ผ์ด์ด๋ฅผ ์ฌ์ฉํด์ ํ์์ ๋ฐ๋ผ '๊ฒ์ผ๋ฅด๊ฒ' ์์ฑ๋๋ ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค ์ ์๋ค.
- ์๋ฐ ์คํธ๋ฆผ์ ์ฌ๊ท์ ์ผ๋ก ์ ์ํ ์ ์๊ธฐ์ ์ ์ฉํ ์ ์๋ค.
- ์ง์ ์ํ๋ผ์ด์ด๋ฅผ ์ฌ์ฉํด ๊ฒ์ผ๋ฅธ ๊ฐ์ฒด ๋ฆฌ์คํธ๋ฅผ ๋ง๋ค ์ ์๋ค.
-
ํจ์ํ์ผ๋ก ๋์์ ์ถ์ํํ๊ณ ์ ๋ฌํจ์ผ๋ก์จ switch๋ฅผ ์ผ๋ฐํํ ์ ์๋ค.
-
์ฐธ์กฐํฌ๋ช ์ฑ(=๊ฐ์ ํ๋ผ๋ฏธํฐ, ๊ฐ์ ๊ฒฐ๊ณผ)์ ์ ์งํ๋ ์ํฉ์์๋ ๊ณ์ฐ ๊ฒฐ๊ณผ๋ฅผ ์บ์ํ ์ ์๋ค.
The Genuine Sieve of Eratosthenes (hmc.edu)
- ์ฃผ์ : ์๋ผํ ์คํ ๋ค์ค์ ์ฒด ์๊ณ ๋ฆฌ์ฆ, ์คํธ๋ฆผ ๊ฒ์ผ๋ฅธ ์ฐ์ฐ