42 ~ 48

์•„์ดํ…œ 42. ์ต๋ช… ํด๋ž˜์Šค๋ณด๋‹ค๋Š” ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ์ž๋ฐ” 8๋ถ€ํ„ฐ ์ž‘์€ ๊ฐ์ฒด๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์ ํ•ฉํ•œ ๋žŒ๋‹ค๊ฐ€ ๋„์ž…๋˜์—ˆ๋‹ค.

ยท ์ต๋ช… ํด๋ž˜์Šค๋Š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์•„๋‹Œ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜์ž.

ยท ๋žŒ๋‹ค๋Š” ์ž‘์€ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ์•„์ฃผ ์‰ฝ๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์–ด (์ด์ „ ์ž๋ฐ”์—์„œ๋Š” ์‹ค์šฉ์ ์ด์ง€ ์•Š๋˜) ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ์ง€ํ‰์„ ์—ด์—ˆ๋‹ค.

์ž๋ฐ” 8 ์ด์ „์˜ ํ•จ์ˆ˜

ยท ์˜ˆ์ „์—๋Š” ์ž๋ฐ”์—์„œ ํ•จ์ˆ˜ ํƒ€์ž…์„ ํ‘œํ˜„ํ•  ๋•Œ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ํ•˜๋‚˜๋งŒ ๋‹ด์€ ์ธํ„ฐํŽ˜์ด์Šค(๋“œ๋ฌผ๊ฒŒ๋Š” ์ถ”์ƒ ํด๋ž˜์Šค)๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

- ์ด๋Ÿฐ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ผ๊ณ  ํ•˜์—ฌ, ํŠน์ • ํ•จ์ˆ˜๋‚˜ ๋™์ž‘์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋ฐ ์ผ๋‹ค.

ยท JDK 1.1 ๋ถ€ํ„ฐ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋งŒ๋“œ๋Š” ์ฃผ์š” ์ˆ˜๋‹จ์€ ์ต๋ช… ํด๋ž˜์Šค(์•„์ดํ…œ 24)๊ฐ€ ๋˜์—ˆ๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ๋Š” ๋ฌธ์ž์—ด์„ ๊ธธ์ด์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๊ธฐ ์œ„ํ•œ ๋น„๊ต ํ•จ์ˆ˜๋กœ ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

// ์ต๋ช… ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•จ์ˆ˜ ๊ฐ์ฒด๋กœ ์‚ฌ์šฉ - ๋‚ก์€ ๊ธฐ๋ฒ•
Collections.sort(words, new Comparator<String>(){
    public int compare(String s1, String s2) {
        return Integer.compare(s1.length(), s2.length());
    }
});

์ „๋žต ํŒจํ„ด[Gamma95]์ฒ˜๋Ÿผ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ณผ๊ฑฐ ๊ฐ์ฒด ์ง€ํ–ฅ ๋””์ž์ธ ํŒจํ„ด์—๋Š” ์ต๋ช… ํด๋ž˜์Šค๋ฉด ์ถฉ๋ถ„ํ–ˆ๋‹ค.

- ์œ„ ์ฝ”๋“œ์—์„œ Comparator ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ •๋ ฌ์„ ๋‹ด๋‹นํ•˜๋Š” ์ถ”์ƒ ์ „๋žต์„ ๋œปํ•˜๊ณ , ๊ตฌ์ฒด์ ์ธ ์ „๋žต์„ ์ต๋ช… ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„ํ–ˆ๋‹ค.

์ต๋ช… ํด๋ž˜์Šค์˜ ๋‹จ์ : ๋„ˆ๋ฌด ๊ธธ๊ธฐ ๋•Œ๋ฌธ์— ์ž๋ฐ”๋Š” ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ์ ํ•ฉํ•˜์ง€ ์•Š์•˜๋‹ค.

์ž๋ฐ” 8 ์ดํ›„์˜ ํ•จ์ˆ˜

ยท ์ž๋ฐ” 8๋ถ€ํ„ฐ ์ถ”์ƒ ๋ฉ”์„œ๋“œ ํ•˜๋‚˜์งœ๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ํŠน๋ณ„ํ•œ ์˜๋ฏธ๋ฅผ ์ธ์ •๋ฐ›์•„ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋กœ ๋ถˆ๋ฆฌ๊ฒŒ ๋˜์—ˆ๊ณ , ์ด ์ธํ„ฐํŽ˜์ด์Šค๋“ค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋žŒ๋‹ค์‹(๋˜๋Š” ๋žŒ๋‹ค)์„ ์‚ฌ์šฉํ•ด ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

ยท ๋žŒ๋‹ค๋Š” ํ•จ์ˆ˜๋‚˜ ์ต๋ช… ํด๋ž˜์Šค์™€ ๊ฐœ๋…์€ ๋น„์Šทํ•˜์ง€๋งŒ, ์ฝ”๋“œ๋Š” ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•˜๋‹ค.

- ๋˜ํ•œ ์ž์งˆ๊ตฌ๋ ˆํ•œ ์ฝ”๋“œ๊ฐ€ ์‚ฌ๋ผ์ ธ ์–ด๋–ค ๋™์ž‘์„ ํ•˜๋Š”์ง€ ๋” ๋ช…ํ™•ํ•˜๋‹ค.

๋‹ค์Œ์€ ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•œ ์•ž์˜ ์ฝ”๋“œ๋ฅผ ๋žŒ๋‹ค ๋ฐฉ์‹์œผ๋กœ ๋ฐ”๊พผ ๋ชจ์Šต์ด๋‹ค.

// ๋žŒ๋‹ค์‹์„ ํ•จ์ˆ˜ ๊ฐ์ฒด๋กœ ์‚ฌ์šฉ - ์ต๋ช… ํด๋ž˜์Šค ๋Œ€์ฒด
Collections.sort(words, (s1, s2) -> Integer.compare(s1.length(), s2.length()));

ยท ์œ„ ์ฝ”๋“œ์—์„œ ๋žŒ๋‹ค, ๋งค๊ฐœ๋ณ€์ˆ˜, ๋ฐ˜ํ™˜๊ฐ’์˜ ํƒ€์ž…์˜ ์–ธ๊ธ‰์€ ์—†๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ๋ฌธ๋งฅ์„ ์‚ดํŽด ํƒ€์ž…์„ ์ถ”๋ก ํ•ด์ค€ ๊ฒƒ์ด๋‹ค.

- ์‹ค์ œ ํƒ€์ž…์€ ๊ฐ๊ฐ (Comprator<String>),String, int๋‹ค.

- ์ƒํ™ฉ์— ๋”ฐ๋ผ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํƒ€์ž…์„ ๊ฒฐ์ •ํ•˜์ง€ ๋ชปํ•  ์ˆ˜๋„ ์žˆ๋Š”๋ฐ, ๊ทธ๋Ÿด ๋•Œ๋Š” ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ง์ ‘ ๋ช…์‹œํ•ด์•ผ ํ•œ๋‹ค.

ยท ์•„์ดํ…œ 26์˜ '์ œ๋„ค๋ฆญ์˜ ๋กœ ํƒ€์ž…์„ ์“ฐ์ง€ ๋ง๋ผ', ์•„์ดํ…œ 29์˜ '์ œ๋„ค๋ฆญ์„ ์“ฐ๋ผ', ์•„์ดํ…œ 30์˜ '์ œ๋„ค๋ฆญ ๋ฉ”์„œ๋“œ๋ฅผ ์“ฐ๋ผ'๊ณ  ํ–ˆ๋˜ ์กฐ์–ธ ๋“ค์€ ๋žŒ๋‹ค์™€ ํ•จ๊ป˜ ์“ธ๋•Œ๋Š” ๋‘ ๋ฐฐ๋กœ ์ค‘์š”ํ•˜๋‹ค. ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ํƒ€์ž…์„ ์ถ”๋ก ํ•˜๋Š” ๋ฐ ํ•„์š”ํ•œ ํƒ€์ž… ์ •๋ณด ๋Œ€๋ถ€๋ถ„์„ ์ œ๋„ค๋ฆญ์—์„œ ์–ป๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- ์šฐ๋ฆฌ๊ฐ€ ์ด ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์œผ๋ฉด ์ปดํŒŒ์ผ๋Ÿฌ๋Š” ๋žŒ๋‹ค์˜ ํƒ€์ž…์„ ์ถ”๋กํ•  ์ˆ˜ ์—†๊ฒŒ ๋˜์–ด, ์šฐ๋ฆฌ๊ฐ€ ์ผ์ผ์ด ๋ช…์‹œํ•ด์•ผํ•œ๋‹ค(์ฝ”๋“œ๊ฐ€ ๋„ˆ์ €๋ถ„ํ•ด์ง).

ยท ํƒ€์ž…์„ ๋ช…์‹œํ•ด์•ผ ์ฝ”๋“œ๊ฐ€ ๋” ๋ช…ํ™•ํ•  ๋•Œ๋งŒ ์ œ์™ธํ•˜๊ณ , ๋žŒ๋‹ค์˜ ๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์€ ์ƒ๋žตํ•˜์ž.

- ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ "ํƒ€์ž…์„ ์•Œ ์ˆ˜ ์—†๋‹ค"๋Š” ์˜ค๋ฅ˜๋ฅผ ๋‚ผ ๋•Œ๋งŒ ํ•ด๋‹น ํƒ€์ž…์„ ๋ช…์‹œํ•œ๋‹ค.

๋žŒ๋‹ค ์ž๋ฆฌ์— ๋น„๊ต ์ƒ์„ฑ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์œ„ ์ฝ”๋“œ๋ฅผ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค(์•„์ดํ…œ 14, 43).

Collections.sort(words, comparingInt(String::length));

์ž๋ฐ” 8์˜ List ์ธํ„ฐํŽ˜์ด์Šค์— ์ถ”๊ฐ€๋œ sort ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜๋ฉด ๋”์šฑ ์งง์•„์ง„๋‹ค.

words.sort( comparingInt(String::length));

๋žŒ๋‹ค์˜ ์žฅ์  - ํ•จ์ˆ˜ ๊ฐ์ฒด์˜ ์‹ค์šฉ์  ์‚ฌ์šฉ

ยท ๋žŒ๋‹ค๋ฅผ ์–ธ์–ด ์ฐจ์›์—์„œ ์ง€์›ํ•˜๋ฉด์„œ ๊ธฐ์กด์—๋Š” ์ ํ•ฉํ•˜์ง€ ์•Š์•˜๋˜ ๊ณณ์—์„œ๋„ ํ•จ์ˆ˜๋ฅผ ์‹ค์šฉ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.

๋‹ค์Œ์€ ์•„์ดํ…œ 34์˜ Operation ์—ด๊ฑฐ ํƒ€์ž…์ด๋‹ค. apply ๋ฉ”์„œ๋“œ์˜ ๋™์ž‘์ด ์ƒ์ˆ˜๋งˆ๋‹ค ๋‹ฌ๋ผ์•ผ ํ•ด์„œ ์ƒ์ˆ˜๋ณ„ ํด๋ž˜์Šค์˜ ๋ชธ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐ ์ƒ์ˆ˜์—์„œ apply ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•ด์•ผํ–ˆ๋‹ค.

public enum Operation {
    PLUS("+") {
        public double apply(double x, double y) { return x + y; }
    },
    MINUS("-") {
        public double apply(double x, double y) { return x - y; }
    },
    TIMES("*") {
        public double apply(double x, double y) { return x * y; }
    },
    DIVIDE("/") {
        public double apply(double x, double y) { return x / y; }
    };
    
    private final String symbol;
    
    Operation(String symbol) { this.symbol = symbol; }
    
    @Override public String toString() { return symbol; }
    public abstract double apply(double x, double y);
}

ยท ๋žŒ๋‹ค๋ฅผ ์ด์šฉํ•˜๋ฉด ์—ด๊ฑฐ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค ์ด์šฉํ•˜์—ฌ, ์ƒ์ˆ˜๋ณ„๋กœ ๋‹ค๋ฅด๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๊ฐ ์—ด๊ฑฐ ํƒ€์ž… ์ƒ์ˆ˜์˜ ๋™์ž‘์„ ๋žŒ๋‹ค๋กœ ๊ตฌํ˜„ํ•ด ์ƒ์„ฑ์ž์— ๋„˜๊ธฐ๊ณ , ์ƒ์„ฑ์ž๋Š” ์ด ๋žŒ๋‹ค๋ฅผ ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋กœ ์ €์Ÿํ•ด๋‘”๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ apply ๋ฉ”์„œ๋“œ์—์„œ ํ•„๋“œ์— ์ €์žฅ๋œ ๋žŒ๋‹ค๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.

- ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„ํ•˜๋ฉด ์›๋ž˜ ๋ฒ„์ „๋ณด๋‹ค ๊ฐ„๊ฒฐํ•˜๊ณ  ๊น”๋”ํ•ด์ง„๋‹ค.

public enum Operation {
    PLUS  ("+", (x, y) -> x + y),
    MINUS ("-", (x, y) -> x - y),
    TIMES ("*", (x, y) -> x * y),
    DIVIDE("/", (x, y) -> x / y);
    
    private final String symbol;
    private final DoubleBinaryOperator op;
    
    Operation(String symbol, DoubleBinaryOperator op) {
        this.symbol = symbol;
        this.op = op;
    }
    
    @Override public String toString() { return symbol; }
    
    public double apply(double x, double y) {
        return op.applyAsDouble(x, y);
    }
}

๋žŒ๋‹ค vs ์ƒ์ˆ˜๋ณ„ ํด๋ž˜์Šค ๋ชธ์ฒด

ยท ๋žŒ๋‹ค๋Š” ์ด๋ฆ„์ด ์—†๊ณ , ๋ฌธ์„œํ™”๋„ ๋ชป ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์ฝ”๋“œ ์ž์ฒด๋กœ ๋™์ž‘์ด ๋ช…ํ™•ํžˆ ์„ค๋ช…๋˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ฝ”๋“œ ์ค„ ์ˆ˜๊ฐ€ ๋งŽ์•„์ง€๋ฉด ์“ฐ์ง€ ๋ง์•„์•ผ ํ•œ๋‹ค.

ยท ๋žŒ๋‹ค๋Š” ๊ธธ์–ด์ง€๋ฉด ๊ฐ€๋…์„ฑ์ด ์‹ฌํ•˜๊ฒŒ ๋‚˜๋น ์ง„๋‹ค.

- ํ•œ ์ค„์ผ ๋•Œ ๊ฐ€์žฅ ์ข‹๊ณ , ๊ธธ์–ด๋„ ์„ธ ์ค„ ์•ˆ์— ๋๋‚ด๋Š” ๊ฒŒ ์ข‹๋‹ค.

- ๋žŒ๋‹ค๊ฐ€ ๊ธธ๊ฑฐ๋‚˜ ์ฝ๊ธฐ ์–ด๋ ต๋‹ค๋ฉด ๋žŒ๋‹ค๋ฅผ ์“ฐ์ง€ ๋ง์•„์•ผ ํ•œ๋‹ค.

ยท ์—ด๊ฑฐ ํƒ€์ž… ์ƒ์„ฑ์ž์— ๋„˜๊ฒจ์ง€๋Š” ์ธ์ˆ˜๋“ค์˜ ํƒ€์ž…์€ ์ปดํŒŒ์ผํƒ€์ž„์— ์ถ”๋ก ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ์—ด๊ฑฐ ํƒ€์ž… ์ƒ์„ฑ์ž ์•ˆ์˜ ๋žŒ๋‹ค๋Š” ์—ด๊ฑฐ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค ๋ฉค๋ฒ„์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†๋‹ค (์ธ์Šคํ„ด์Šค๋Š” ๋Ÿฐํƒ€์ž„์— ๋งŒ๋“ค์–ด์ง€๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค).

ยท ์ƒ์ˆ˜๋ณ„ ๋™์ž‘์„ ๋‹จ ๋ช‡ ์ค„๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ ์–ด๋ ต๊ฑฐ๋‚˜, ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋‚˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์•ผ๋งŒ ํ•˜๋Š” ์ƒํ™ฉ์ด๋ฉด, ์ƒ์ˆ˜๋ณ„ ํด๋ž˜์Šค ๋ชธ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์ž.

๋žŒ๋‹ค vs ์ต๋ช…ํด๋ž˜์Šค

ยท ๋žŒ๋‹ค๋Š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์—์„œ๋งŒ ์“ฐ์ด๋ฏ€๋กœ, ์ถ”์ƒ ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ ๋žŒ๋‹ค๋ฅผ ์“ธ ์ˆ˜ ์—†์œผ๋‹ˆ ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ์จ์•ผ ํ•œ๋‹ค.

ยท ์ถ”์ƒ ๋ฉ”์„œ๋“œ๊ฐ€ ์—ฌ๋Ÿฌ ๊ฐœ์ธ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

ยท ํ•จ์ˆ˜ ๊ฐ์ฒด๊ฐ€ ์ž์‹ ์„ ์ฐธ์กฐํ•ด์•ผ ํ•œ๋‹ค๋ฉด ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ์จ์•ผ ํ•œ๋‹ค.

- ๋žŒ๋‹ค๋Š” ์ž์‹ ์„ ์ฐธ์กฐํ•  ์ˆ˜ ์—†๋‹ค. ๋žŒ๋‹ค์—์„œ this ํ‚ค์›Œ๋“œ๋Š” ๋ฐ”๊นฅ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

- ๋ฐ˜๋ฉด, ์ต๋ช…ํด๋ž˜์Šค์—์„œ์˜ this๋Š” ์ต๋ช… ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค ์ž์‹ ์„ ๊ฐ€๋ฆฌํ‚จ๋‹ค.

ยท ๋žŒ๋‹ค๋„ ์ต๋ช… ํด๋ž˜์Šค์ฒ˜๋Ÿผ ์ง๋ ฌํ™” ํ˜•ํƒœ๊ฐ€ ๊ตฌํ˜„๋ณ„๋กœ(์˜ˆ: ๊ฐ€์ƒ๋จธ์‹ ๋ณ„๋กœ) ๋‹ค๋ฅผ ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋žŒ๋‹ค๋ฅผ ์ง๋ ฌํ™”ํ•˜๋Š” ์ผ์€ ์‚ผ๊ฐ€์•ผ ํ•œ๋‹ค(์ต๋ช… ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๋กœ ๋งˆ์ฐฌ๊ฐ€์ง€).

- ์ง๋ ฌํ™”ํ•ด์•ผ๋งŒ ํ•˜๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด๊ฐ€ ์žˆ๋‹ค๋ฉด(Comparator ๋“ฑ) private ์ •์  ์ค‘์ฒฉ ํด๋ž˜์Šค(์•„์ดํ…œ 24)์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜์ž.

์•„์ดํ…œ 43. ๋žŒ๋‹ค๋ณด๋‹ค๋Š” ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋Š” ๋žŒ๋‹ค์˜ ๊ฐ„๋‹จ๋ช…๋ฃŒํ•œ ๋Œ€์•ˆ์ด ๋  ์ˆ˜ ์žˆ๋‹ค. ๋ฉ”์„œ๋“œ ์ฐธ์กฐ ์ชฝ์ด ์งง๊ณ  ๋ช…ํ™•ํ•˜๋‹ค๋ฉด ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์“ฐ๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์„ ๋•Œ๋งŒ ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•˜๋ผ.

๋ฉ”์„œ๋“œ ์ฐธ์กฐ

ยท ๋ฉ”์„œ๋“œ ์ฐธ์กฐ(method reference)๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋žŒ๋‹ค๋ณด๋‹ค๋„ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

๋ฉ”์„œ๋“œ ์ฐธ์กฐ ์‚ฌ์šฉ ์˜ˆ์‹œ

๋‹ค์Œ ์ฝ”๋“œ๋Š” ์ž„์˜์˜ ํ‚ค์™€ Integer ๊ฐ’์˜ ๋งคํ•‘์„ ๊ด€๋ฆฌํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์˜ ์ผ๋ถ€๋‹ค. ํ‚ค๊ฐ€ ๋งต ์•ˆ์— ์—†๋‹ค๋ฉด ํ‚ค์™€ ์ˆซ์ž 1์„ ๋งคํ•‘ํ•˜๊ณ , ์ด๋ฏธ ์žˆ๋‹ค๋ฉด ๊ธฐ์กด ๋งคํ•‘ ๊ฐ’์„ ์ฆ๊ฐ€์‹œํ‚จ๋‹ค.

map.merge(key, 1, (count, incr) -> count + incr);

์ด ์ฝ”๋“œ๋Š” ์ž๋ฐ” 8 ๋•Œ Mpap์— ์ถ”๊ฐ€๋œ merge ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. merge ๋ฉ”์„œ๋“œ๋Š” ํ‚ค, ๊ฐ’, ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์œผ๋ฉฐ, ์ฃผ์–ด์ง„ ํ‚ค๊ฐ€ ๋งต ์•ˆ์— ์•„์ง ์—†๋‹ค๋ฉด ์ฃผ์–ด์ง„ [ํ‚ค, ๊ฐ’] ์Œ์„ ๊ทธ๋Œ€๋กœ ์ €์žฅํ•œ๋‹ค. ๋ฐ˜๋Œ€๋กœ ํ‚ค๊ฐ€ ์ด๋ฏธ ์žˆ๋‹ค๋ฉด, ์„ธ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋ฐ›์€ ํ•จ์ˆ˜๋ฅผ ํ˜„์žฌ ๊ฐ’๊ณผ ์ฃผ์–ด์ง„ ๊ฐ’์— ์ ์šฉํ•œ ๋‹ค์Œ, ๊ทธ ๊ฒฐ๊ณผ๋กœ ํ˜„์žฌ ๊ฐ’์„ ๋ฎ์–ด์“ด๋‹ค.

ยท ๋žŒ๋‹ค ๋Œ€์‹  ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์ „๋‹ฌํ•˜๋ฉด ๋˜‘๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ๋” ๋ณด๊ธฐ ์ข‹๊ฒŒ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

- ๋งค๊ฐœ๋ณ€์ˆ˜ count์™€ incr๋Š” ํฌ๊ฒŒ ํ•˜๋Š” ์ผ ์—†์ด ๊ณต๊ฐ„์„ ๊ฝค ์ฐจ์ง€ํ•œ๋‹ค.

- ์ž๋ฐ” 8์ด ๋˜๋ฉด์„œ ๊ธฐ๋ณธ ํƒ€์ž…์˜ ๋ฐ•์‹ฑ ํƒ€์ž…์€ ์ด ๋žŒ๋‹ค์™€ ๊ธฐ๋Šฅ์ด ๊ฐ™์€ ์ •์  ๋ฉ”์„œ๋“œ sum์„ ์ œ๊ณตํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋‹ค.

map.merge(key, 1, Integer::sum);

๋ฉ”์„œ๋“œ ์ฐธ์กฐ์™€ ๋žŒ๋‹ค์˜ ์ฐจ์ด์ 

ยท ๋งค๊ฐœ๋ณ€์ˆ˜ ์ˆ˜๊ฐ€ ๋Š˜์–ด๋‚ ์ˆ˜๋ก ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋กœ ์ œ๊ฑฐํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ์–‘๋„ ๋Š˜์–ด๋‚œ๋‹ค. ํ•˜์ง€๋งŒ ์–ด๋–ค ๋žŒ๋‹ค์—์„œ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ด๋ฆ„ ์ž์ฒด๊ฐ€ ํ”„๋กœ๊ทธ๋ž˜๋จธ์—๊ฒŒ ์ข‹์€ ๊ฐ€์ด๋“œ๊ฐ€ ๋˜๊ธฐ๋„ ํ•œ๋‹ค. ์ด๋Ÿฐ ๋žŒ๋‹ค๋Š” ๊ธธ์ด๋Š” ๋” ๊ธธ์ง€๋งŒ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ณด๋‹ค ์ฝ๊ธฐ ์‰ฝ๊ณ  ์œ ์ง€๋ณด์ˆ˜๋„ ์‰ฌ์šธ ์ˆ˜ ์žˆ๋‹ค.

ยท ๋žŒ๋‹ค๋กœ ํ•  ์ˆ˜ ์—†๋Š” ์ผ์ด๋ผ๋ฉด ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋กœ๋„ ํ•  ์ˆ˜ ์—†๋‹ค.

- ๋‹จ, ์œ ์ผํ•œ ์˜ˆ์™ธ๊ฐ€ ์กด์žฌํ•œ๋‹ค. ์ œ๋„ค๋ฆญ ํ•จ์ˆ˜ ํƒ€์ž… ๊ตฌํ˜„์ด๋‹ค. ์ œ๋„ค๋ฆญ ํ•จ์ˆ˜ ํƒ€์ž…์€ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ ํ‘œํ˜„์‹์œผ๋กœ๋Š” ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๋žŒ๋‹ค์‹์œผ๋กœ๋Š” ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ธํ„ฐํŽ˜์ด์Šค ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ์ƒ๊ฐํ•ด๋ณด์ž.

interface G1 {
    <E extends Exception> Object m() throws E;
        }
        
        interface G2 {
            <F extends Exception> String m() throws Exception;
                }
                
                interface G extends G1, G2 {
                }

์ด๋•Œ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค G๋ฅผ ํ•จ์ˆ˜ ํƒ€์ž…์œผ๋กœ ํ‘œํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

F extends Exception> () -> String throws F

ยท ๋ฉ”์„œ๋“œ ์ฐธ์กฐ์—๋Š” ๊ธฐ๋Šฅ์„ ์ž˜ ๋“œ๋Ÿฌ๋‚ด๋Š” ์ด๋ฆ„์„ ์ง€์–ด์ค„ ์ˆ˜ ์žˆ๊ณ , ์นœ์ ˆํ•œ ์„ค๋ช…์„ ๋ฌธ์„œ๋กœ ๋‚จ๊ธธ ์ˆ˜๋„ ์žˆ๋‹ค.

ยท ๋žŒ๋‹ค๊ฐ€ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ณด๋‹ค ๊ฐ„๊ฒฐํ•  ๋•Œ๊ฐ€ ์žˆ๋‹ค. ์ฃผ๋กœ ๋ฉ”์„œ๋“œ์™€ ๋žŒ๋‹ค๊ฐ€ ๊ฐ™์€ ํด๋ž˜์Šค์— ์žˆ์„ ๋•Œ ๊ทธ๋ ‡๋‹ค.

ex) ๋‹ค์Œ ์ฝ”๋“œ๊ฐ€ GoshThisClassNameIsHumongous ํด๋ž˜์Šค ์•ˆ์— ์žˆ๋‹ค๊ณ  ํ•ด๋ณด์ž.

service.execute(GoshThisClassNameIsHumongous::action);

์ด๋ฅผ ๋žŒ๋‹ค๋กœ ๋Œ€์ฒดํ•˜๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ๋œ๋‹ค. ์ด ๊ฒฝ์šฐ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ ์ชฝ์€ ๋” ์งง์ง€๋„, ๋” ๋ช…ํ™•ํ•˜์ง€๋„ ์•Š๋‹ค. ๋”ฐ๋ผ์„œ ๋žŒ๋‹ค ์ชฝ์ด ๋‚ซ๋‹ค.

service.execute(() -> action());

๊ฐ™์€ ์„ ์ƒ์—์„œ java.util.function ํŒจํ‚ค์ง€๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ œ๋„ค๋ฆญ ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ์ธ Function.identity()๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋ณด๋‹ค๋Š” ๋˜‘๊ฐ™์€ ๊ธฐ๋Šฅ์˜ (x -> x)๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ์ฝ”๋“œ๋„ ์งง๊ณ  ๋ช…ํ™•ํ•˜๋‹ค.

๋ฉ”์„œ๋“œ ์ฐธ์กฐ์˜ ์œ ํ˜•

ยท ๋ฉ”์„œ๋“œ ์ฐธ์กฐ์˜ ์œ ํ˜•์€ ๋‹ค์„ฏ ๊ฐ€์ง€๊ฐ€ ์žˆ๋‹ค.

1. ์ •์  ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”์„œ๋“œ ์ฐธ์กฐ

์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์œ ํ˜• ๋‘ ๊ฐ€์ง€

2. ์ˆ˜์‹  ๊ฐ์ฒด(receiving object, ์ฐธ์กฐ ๋Œ€์ƒ ์ธ์Šคํ„ด์Šค)๋ฅผ ํŠน์ •ํ•˜๋Š” ํ•œ์ •์ (bound) ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ์ฐธ์กฐ

- ํ•œ์ •์  ์ฐธ์กฐ๋Š” ๊ทผ๋ณธ์ ์œผ๋กœ ์ •์  ์ฐธ์กฐ์™€ ๋น„์Šทํ•˜๋‹ค. ์ฆ‰, ํ•จ์ˆ˜ ๊ฐ์ฒด๊ฐ€ ๋ฐ›๋Š” ์ธ์ˆ˜์™€ ์ฐธ์กฐ๋˜๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ›๋Š” ์ธ์ˆ˜๊ฐ€ ๋˜‘๊ฐ™๋‹ค.

3. ์ˆ˜์‹  ๊ฐ์ฒด๋ฅผ ํŠน์ •ํ•˜์ง€ ์•Š๋Š” ๋น„ํ•œ์ •์ (unbound) ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ์ฐธ์กฐ

- ๋น„ํ•œ์ •์  ์ฐธ์กฐ์—์„œ๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ์ ์šฉํ•˜๋Š” ์‹œ์ ์— ์ˆ˜์‹  ๊ฐ์ฒด๋ฅผ ์•Œ๋ ค์ค€๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ์ˆ˜์‹  ๊ฐ์ฒด ์ „๋‹ฌ์šฉ ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ๋งค๊ฐœ๋ณ€์ˆ˜ ๋ชฉ๋ก์˜ ์ฒซ ๋ฒˆ์งธ๋กœ ์ถ”๊ฐ€๋˜๋ฉฐ, ๊ทธ ๋’ค๋กœ๋Š” ์ฐธ์กฐ๋˜๋Š” ๋ฉ”์„œ๋“œ ์„ ์–ธ์— ์ •์˜๋œ ๋งค๊ฐœ๋ณ€์ˆ˜๋“ค์ด ๋’ค๋”ฐ๋ฅธ๋‹ค.

- ๋น„ํ•œ์ •์  ์ฐธ์กฐ๋Š” ์ฃผ๋กœ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ์˜ ๋งคํ•‘๊ณผ ํ•„ํ„ฐ ํ•จ์ˆ˜์— ์“ฐ์ธ๋‹ค(์•„์ดํ…œ 45).

4. ํด๋ž˜์Šค ์ƒ์„ฑ์ž๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”์„œ๋“œ ์ฐธ์กฐ

5. ๋ฐฐ์—ด ์ƒ์„ฑ์ž๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋Š” ๋ฉ”์„œ๋“œ ์ฐธ์กฐ

- ์ƒ์„ฑ์ž ์ฐธ์กฐ๋Š” ํŒฉํ„ฐ๋ฆฌ ๊ฐ์ฒด๋กœ ์‚ฌ์šฉ๋œ๋‹ค.

๋ฉ”์„œ๋“œ ์ฐธ์กฐ ์œ ํ˜•์˜ˆ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ๋žŒ๋‹ค

์ •์ 

Integer::parseInt

str -> Integer.parseInt(str)

ํ•œ์ •์ (์ธ์Šคํ„ด์Šค)

Instant.now::isAfter

Instant then = Instant.now(); t -> then.isAfter(t)

๋น„ํ•œ์ •์ (์ธ์Šคํ„ด์Šค)

String::toLowerCase

str -> str.toLowerCase()

ํด๋ž˜์Šค ์ƒ์„ฑ์ž

TreeMap<K, V>::new

() -> new TreeMap<K, V>()

๋ฐฐ์—ด ์ƒ์„ฑ์ž

int[]::new

len -> new int[len]

์•„์ดํ…œ 44. ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ์ž๋ฐ”8 ๋ถ€ํ„ฐ ๋žŒ๋‹ค๋ฅผ ์ง€์›ํ•˜๋ฏ€๋กœ, API๋ฅผ ์„ค๊ณ„ํ•  ๋•Œ ๋žŒ๋‹ค๋„ ์—ผ๋‘์— ๋‘์–ด์•ผ ํ•œ๋‹ค.

ยท ์ž…๋ ฅ๊ฐ’๊ณผ ๋ฐ˜ํ™˜๊ฐ’์— ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์„ ํ™œ์šฉํ•˜์ž.

ยท ๋ณดํ†ต java.util.function ํŒจํ‚ค์ง€์˜ ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์€ ์„ ํƒ์ด๋‹ค.

ยท ๋‹จ, ํ”์น˜๋Š” ์•Š์ง€๋งŒ ์ง์ ‘ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๋งŒ๋“ค์–ด ์“ฐ๋Š” ํŽธ์ด ๋‚ณ์„ ์ˆ˜๋„ ์žˆ๋‹ค.

๋žŒ๋‹ค์™€ API ์ž‘์„ฑ ๋ชจ๋ฒ” ์‚ฌ๋ก€

ยท ์ž๋ฐ”๊ฐ€ ๋žŒ๋‹ค๋ฅผ ์ง€์›ํ•˜๋ฉด์„œ API๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ชจ๋ฒ” ์‚ฌ๋ก€๋„ ํฌ๊ฒŒ ๋ฐ”๋€Œ์—ˆ๋‹ค.

- ์ƒ์œ„ ํด๋ž˜์Šค์˜ ๊ธฐ๋ณธ ๋ฉ”์„œ๋“œ๋ฅผ ์žฌ์ •์˜ํ•ด ์›ํ•˜๋Š” ๋™์ž‘์„ ๊ตฌํ˜„ํ•˜๋Š” ํ…œํ”Œ๋ฆฌ ๋ฉ”์„œ๋“œ ํŒจํ„ด[Gamma95]์˜ ๋งค๋ ฅ์ด ํฌ๊ฒŒ ์ค„์—ˆ๋‹ค. ์ด๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ํ˜„๋Œ€์ ์ธ ํ•ด๋ฒ•์€ ๊ฐ™์€ ํšจ๊ณผ์˜ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ๋‚˜ ์ƒ์„ฑ์ž๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

ยท ์œ„ ๋‚ด์šฉ์„ ์ผ๋ฐ˜ํ™”ํ•˜๋ฉด, ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š” ์ƒ์„ฑ์ž์™€ ๋ฉ”์„œ๋“œ๋ฅผ ๋” ๋งŽ์ด ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

- ์ด๋•Œ ํ•จ์ˆ˜ํ˜• ๋งค๊ฐœ๋ณ€์ˆ˜ ํƒ€์ž…์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์„ ํƒํ•ด์•ผ ํ•œ๋‹ค.

ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋Š” ์˜ˆ์‹œ

LinkedHashMap์˜ protected ๋ฉ”์„œ๋“œ์ธ removeEldestEntry๋ฅผ ์žฌ์ •์˜ํ•˜๋ฉด ์บ์‹œ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ๋งต์— ์ƒˆ๋กœ์šด ํ‚ค๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” put ๋ฉ”์„œ๋“œ๋Š” ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ true๊ฐ€ ๋ฐ˜ํ™˜๋˜๋ฉด ๋งต์—์„œ ๊ฐ€์žฅ ์˜ค๋ž˜๋œ ์›์†Œ๋ฅผ ์ œ๊ฑฐํ•œ๋‹ค.

๋‹ค์Œ ์ฒ˜๋Ÿผ removeEldestEntry๋ฅผ ์žฌ์ •์˜ํ•˜๋ฉด ๋งต์— ๊ฐ€์žฅ ์ตœ๊ทผ ์›์†Œ 100๊ฐœ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.

protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {
    return size() > 100;
}

์œ„ ์ฝ”๋“œ๋Š” ์ž˜ ๋™์ž‘ํ•˜์ง€๋งŒ, ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ›จ์”ฌ ์ž˜ ํ•ด๋‚ผ ์ˆ˜ ์žˆ๋‹ค. LinkedHashMap์„ ์˜ค๋Š˜๋‚  ๋‹ค์‹œ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด, ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ๋ฐ›๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ๋‚˜ ์ƒ์„ฑ์ž๋ฅผ ์ œ๊ณตํ–ˆ์„ ๊ฒƒ์ด๋‹ค.

removeEldestEntry๋Š” size()๋ฅผ ํ˜ธ์ถœํ•ด ๋งต ์•ˆ์˜ ์›์†Œ ์ˆ˜๋ฅผ ์•Œ์•„๋‚ธ๋‹ค. removeEldestEntry๊ฐ€ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๋ผ ๊ฐ€๋Šฅํ•œ ๋ฐฉ์‹์ด๋‹ค. ํ•˜์ง€๋งŒ ์ƒ์„ฑ์ž์— ๋„˜๊ธฐ๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด๋Š” ์ด ๋งต์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹ˆ๋‹ค. ํŒฉํ„ฐ๋ฆฌ๋‚˜ ์ƒ์„ฑ์ž๋ฅผ ํ˜ธ์ถœํ•  ๋•Œ๋Š” ๋งต์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋”ฐ๋ผ์„œ ๋งต์€ ์ž๊ธฐ ์ž์‹ ๋„ ํ•จ์ˆ˜ ๊ฐ์ฒด์— ๊ฑด๋„ค์ค˜์•ผ ํ•œ๋‹ค.

์ด๋ฅผ ๋ฐ˜์˜ํ•œ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

// ๋ถˆํ•„์š”ํ•œ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค - ๋Œ€์‹  ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ผ.
@FunctionalInterface interface EldestEntryRemovalFunction<K,V> {
    boolean remove( Map<K,V> map, Map.Entry<K,V> eldest );
        }

์ด ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ž˜ ๋™์ž‘ํ•˜๋‚˜, ๊ตณ์ด ์‚ฌ์šฉํ•  ์ด์œ ๋Š ์—†๋‹ค. ์ž๋ฐ” ํ‘œ์ค€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์— ์ด๋ฏธ ๊ฐ™์€ ๋ชจ์–‘์˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ค€๋น„๋˜์–ด ์žˆ๋‹ค.

ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค

ยท java.util.function ํŒจํ‚ค์ง€๋ฅผ ๋ณด๋ฉด ๋‹ค์–‘ํ•œ ์šฉ๋„์˜ ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋‹ด๊ฒจ ์žˆ๋‹ค.

ํ•„์š”ํ•œ ์šฉ๋„์— ๋งž๋Š” ๊ฒŒ ์žˆ๋‹ค๋ฉด, ์ง์ ‘ ๊ตฌํ˜„ํ•˜์ง€ ๋ง๊ณ  ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ™œ์šฉํ•˜์ž.

ยท ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ์‚ฌ์šฉ์˜ ์žฅ์ :

1. API๊ฐ€ ๋‹ค๋ฃจ๋Š” ๊ฐœ๋…์˜ ์ˆ˜๊ฐ€ ์ค„์–ด ์ตํžˆ๊ธฐ ๋” ์‰ฌ์›Œ ์ง„๋‹ค.

2. ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋“ค์€ ์œ ์šฉํ•œ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŽ์ด ์ œ๊ณตํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ๋‹ค๋ฅธ ์ฝ”๋“œ์™€์˜ ์ƒํ˜ธ์šด์šฉ์„ฑ๋„ ํฌ๊ฒŒ ์ข‹์•„์ง„๋‹ค.

ex) Predicate ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํ”„๋ ˆ๋””ํ‚ค๋“œ(predicate)๋“ค์„ ์กฐํ•ฉํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค. LinkedHashMap ์˜ˆ์—์„œ๋Š” ์ง์ ‘ ๋งŒ๋“  EledestEntryRemoveFuntion ๋Œ€์‹  ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค์ธ BiPredicate<Map<K, V>>, Map.Entry<K, V>๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท java.util.function ํŒจํ‚ค์ง€์—๋Š” ์ด 43๊ฐœ์˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋‹ด๊ฒจ ์žˆ๋‹ค. ๊ทธ ์ค‘ ๊ธฐ๋ณธ ์ธํ„ฐํŽ˜์ด์Šค 6๊ฐœ๋งŒ ๊ธฐ์–ตํ•˜๋ฉด ๋‚˜๋จธ์ง€๋ฅผ ์œ ์ถ”ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ๊ธฐ๋ณธ ์ธํ„ฐํŽ˜์ด์Šค๋“ค์€ ๋ชจ๋‘ ์ฐธ์กฐ ํƒ€์ž…์šฉ์ด๋‹ค.

๊ธฐ๋ณธ ์ธํ„ฐํŽ˜์ด์Šค

ยท Operator ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธ์ˆ˜๊ฐ€ 1๊ฐœ์ธ UnaryOperator์™€ 2๊ฐœ์ธ BinaryOperator๋กœ ๋‚˜๋‰˜๋ฉฐ, _๋ฐ˜ํ™˜๊ฐ’๊ณผ ์ธ์ˆ˜์˜ ํƒ€์ž…์ด ๊ฐ™์€ ํ•จ์ˆ˜_๋ฅผ ๋œปํ•œ๋‹ค.

ยท Predicate ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธ์ˆ˜ ํ•˜๋‚˜๋ฅผ ๋ฐ›์•„ boolean์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋œปํ•œ๋‹ค.

ยท Function ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธ์ˆ˜์™€ ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋‹ค๋ฅธ ํ•จ์ˆ˜๋ฅผ ๋œปํ•œ๋‹ค.

ยท Supplier ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธ์ˆ˜๋ฅผ ๋ฐ›์ง€ ์•Š๊ณ  ๊ฐ’์„ ๋ฐ˜ํ™˜(ํ˜น์€ ์ œ๊ณต)ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋œปํ•œ๋‹ค.

ยท Consumer ์ธํ„ฐํŽ˜์ด์Šค๋Š” ์ธ์ˆ˜๋ฅผ ํ•˜๋‚˜ ๋ฐ›๊ณ  ๋ฐ˜ํ™˜๊ฐ’์€ ์—†๋Š”(ํŠนํžˆ ์ธ์ˆ˜๋ฅผ ์†Œ๋น„ํ•˜๋Š”) ํ•จ์ˆ˜๋ฅผ ๋œปํ•œ๋‹ค.

๋‹ค์Œ์€ ๊ธฐ๋ณธ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋“ค์„ ์ •๋ฆฌํ•œ ํ‘œ๋‹ค.

๊ธฐ๋ณธ ์ธํ„ฐํŽ˜์ด์Šค์˜ ๋ณ€ํ˜•

ยท ๊ธฐ๋ณธ ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ธฐ๋ณธ ํƒ€์ž…์ธ int, long, double์šฉ์œผ๋กœ ๊ฐ 3๊ฐœ์”ฉ ๋ณ€ํ˜•์ด ์ƒ๊ธด๋‹ค.

- ์ด๋ฆ„์€ ๊ธฐ๋ณธ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ด๋ฆ„ ์•ž์— ํ•ด๋‹น ๊ธฐ๋ณธ ํƒ€์ž… ์ด๋ฆ„์„ ๋ถ™์—ฌ ์ง€์—ˆ๋‹ค.

ex) int๋ฅผ ๋ฐ›๋Š” Predicate๋Š” IntPredicate, long์„ ๋ฐ›์•„ long์„ ๋ฐ˜ํ™˜ํ•˜๋Š” BinaryOperator๋Š” LongBinaryOperator๊ฐ€ ๋˜๋Š” ์‹์ด๋‹ค.

ยท Function์˜ ๋ณ€ํ˜•์€ ์œ ์ผํ•˜๊ฒŒ ๋ฐ˜ํ™˜ ํƒ€์ž…์ด ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋œ๋‹ค.

ex) LongFunction<int[]>์€ long ์ธ์ˆ˜๋ฅผ ๋ฐ›์•„ int[]๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

ยท Function ์ธํ„ฐํŽ˜์ด์Šค์—๋Š” ๊ธฐ๋ณธ ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ณ€ํ˜•์ด ์ด 9๊ฐœ ๋” ์žˆ๋‹ค.

- ์ž…๋ ฅ๊ณผ ๊ฒฐ๊ณผ ํƒ€์ž…์ด ๋ชจ๋‘ ๊ธฐ๋ณธ ํƒ€์ž…์ด๋ฉด ์ ‘๋‘์–ด๋กœ SrcToResult๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค(์ด 6๊ฐœ).

ex) long์„ ๋ฐ›์•„ int๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋ฉด LongToIntFunction์ด ๋˜๋Š” ์‹์ด๋‹ค.

- ๋‚˜๋จธ์ง€๋Š” ์ž…๋ ฅ์ด ๊ฐ์ฒด ์ฐธ์กฐ์ด๊ณ  ๊ฒฐ๊ณผ๊ฐ€ int, long, double์ธ ๋ณ€ํ˜•๋“ค๋กœ, ์•ž์„œ์™€ ๋‹ฌ๋ฆฌ ์ž…๋ ฅ์„ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”ํ•˜๊ณ  ์ ‘๋‘์–ด๋กœ ToResult๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค(์ด 3๊ฐœ).

ex) int[] ์ธ์ˆ˜๋ฅผ ๋ฐ›์•„ long์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ToLongFunction<int[]>์ด ๋˜๋Š” ์‹์ด๋‹ค.

ยท ๊ธฐ๋ณธ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ์ค‘ 3๊ฐœ์—๋Š” ์ธ์ˆ˜๋ฅผ 2๊ฐœ์”ฉ ๋ฐ›๋Š” ๋ณ€ํ˜•์ด ์žˆ๋‹ค(์ด 6๊ฐœ).

- BiPredicate<T, U>, BiFunction<T,U,R>, BiConsumer<T,U>์ด๋‹ค.

- BiFunction์€ ๊ธฐ๋ณธ ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์„ธ ๋ณ€ํ˜• ToIntBiFunction<T,U>, ToLongBiFunction<T,U>, ToDoubleBiFunction<T,U>๊ฐ€ ์กด์žฌํ•œ๋‹ค.

ยท Consumer์—๋Š” ๊ฐ์ฒด ์ฐธ์กฐ์™€ ๊ธฐ๋ณธ ํƒ€์ž… ํ•˜๋‚˜, ์ฆ‰ ์ธ์ˆ˜๋ฅผ 2๊ฐœ ๋ฐ›๋Š” ๋ณ€ํ˜•์ธ ObjDoubleConsumer<T>, ObjIntConsumer<T>, ObjLongConsumer<T>๊ฐ€ ์กด์žฌํ•œ๋‹ค(์ด 3๊ฐœ).

- ์ด๋ ‡๊ฒŒ ํ•ด์„œ ๊ธฐ๋ณธ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ธ์ˆ˜ 2๊ฐœ์งœ๋ฆฌ ๋ณ€ํ˜•์„ ์ด 9๊ฐœ๋‹ค.

ยท BooleanSupplier ์ธํ„ฐํŽ˜์ด์Šค๋Š” boolean์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•œ Supplier์˜ ๋ณ€ํ˜•์ด๋‹ค.

- ์ด๊ฒƒ์€ ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ์ค‘ boolean์„ ์ด๋ฆ„์— ๋ช…์‹œํ•œ ์œ ์ผํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋‹ค.

- ํ•˜์ง€๋งŒ Predicate์™€ ๊ทธ ๋ณ€ํ˜• 4๊ฐœ๋„ boolean ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ๋Œ€๋ถ€๋ถ„์€ ๊ธฐ๋ณธ ํƒ€์ž…๋งŒ ์ง€์›ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์—ฌ๊ธฐ์— ๋ฐ•์‹ฑ๋œ ๊ธฐ๋ณธ ํƒ€์ž…์„ ๋„ฃ์–ด ์‚ฌ์šฉํ•˜์ง€๋Š” ๋ง์ž

- ๊ณ„์‚ฐ๋Ÿ‰์ด ๋งŽ์„ ๋–„ ์„ฑ๋Šฅ์ด ์ฒ˜์ฐธํžˆ ๋Š๋ ค์งˆ ์ˆ˜ ์žˆ๋‹ค(์•„์ดํ…œ 61).

์ „์šฉ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ์ง์ ‘ ์ž‘์„ฑํ•ด์•ผ ํ•  ๋•Œ

ยท ๋Œ€๋ถ€๋ถ„ ์ƒํ™ฉ์—์„œ ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ‘œ์ค€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ํŽธ์ด ๋‚ซ์ง€๋งŒ, ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์ž‘์„ฑํ•ด์•ผํ•  ๋•Œ๋„ ์žˆ๋‹ค.

ยท ํ‘œ์ค€ ์ธํ„ฐํŽ˜์ด์Šค ์ค‘ ํ•„์š”ํ•œ ์šฉ๋„์— ๋งž๋Š” ๊ฒŒ ์—†๋‹ค๋ฉด ์ง์ ‘ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.

ex) ๋งค๊ฐœ๋ณ€์ˆ˜ 3๊ฐœ๋ฅผ ๋ฐ›๋Š” Predicate, ๊ฒ€์‚ฌ ์˜ˆ์™ธ๋ฅผ ๋˜์ง€๋Š” ๊ฒฝ์šฐ

ยท ๊ตฌ์กฐ์ ์œผ๋กœ ๋˜‘๊ฐ™์ง€๋งŒ, ๋‹ค์Œ์„ ํ•˜๋‚˜ ์ด์ƒ ๋งŒ์กฑํ•œ๋‹ค๋ฉด ์ง์ ‘ ์ž‘์„ฑํ•˜๋Š” ๊ฒƒ์„ ๊ณ ๋ คํ•œ๋‹ค.

1. ์ž์ฃผ ์“ฐ์ด๋ฉฐ, ์ด๋ฆ„ ์ž์ฒด๊ฐ€ ์šฉ๋„๋ฅผ ๋ช…ํ™•ํžˆ ์„ค๋ช…ํ•œ๋‹ค.

2. ๋ฐ˜๋“œ์‹œ ๋”ฐ๋ผ์•ผ ํ•˜๋Š” ๊ทœ์•ฝ์ด ์žˆ๋‹ค.

3. ์œ ์šฉํ•œ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด Comparator<T> ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๊ตฌ์กฐ์ ์œผ๋กœ ToIntBiFunction<T,U๊ณผ ๋™์ผํ•˜์ง€๋งŒ, ์œ„์™€ ๊ฐ™์€ ํŠน์„ฑ์„ ๋ชจ๋‘ ์ง€๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ „์šฉ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋งŒ๋“ค์–ด์กŒ๋‹ค.

์ „์šฉ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ์„ค๊ณ„ํ•˜๊ธฐ

ยท ์ „์šฉ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ๋กœ ํ–ˆ๋‹ค๋ฉด, ์ž‘์„ฑํ•˜๋Š” ๊ฒŒ '์ธํ„ฐํŽ˜์ด์Šค'์ž„์„ ๋ช…์‹ฌํ•˜๊ณ  ์ฃผ์˜ํ•ด์„œ ์„ค๊ณ„ํ•ด์•ผ ํ•œ๋‹ค.

ยท ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์— @FunctionalInterface ์• ๋„ˆํ…Œ์ด์…˜์„ ๋‹ฌ๋ฉด, ๋‹ค์Œ์˜ ํšจ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

1. ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ฝ”๋“œ๋‚˜ ์„ค๋ช… ๋ฌธ์„œ๋ฅผ ์ฝ์„ ์ด์—๊ฒŒ ๊ทธ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ๋žŒ๋‹ค์šฉ์œผ๋กœ ์„ค๊ณ„๋œ ๊ฒƒ์ž„์„ ์•Œ๋ ค์ค€๋‹ค.

2. ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์˜ค์ง ํ•˜๋‚˜๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์–ด์•ผ ์ปดํŒŒ์ผ๋˜๊ฒŒ ํ•ด์ค€๋‹ค.

3. 2๋ฒˆ์˜ ๊ฒฐ๊ณผ๋กœ, ์œ ์ง€๋ณด์ˆ˜ ๊ณผ์ •์—์„œ ๋ˆ„๊ตฐ๊ฐ€ ์‹ค์ˆ˜๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•˜์ง€ ๋ชปํ•˜๊ฒŒ ๋ง‰์•„์ค€๋‹ค.

์œ„์™€ ๊ฐ™์€ ์ด์ ์ด ์žˆ์œผ๋‹ˆ, ์ง์ ‘ ๋งŒ๋“  ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์—๋Š” ํ•ญ์ƒ @FunctionalInterface ์• ๋„ˆํ…Œ์ด์…˜์„ ์‚ฌ์šฉํ•˜์ž.

์ฃผ์˜ ์‚ฌํ•ญ! ์„œ๋กœ ๋‹ค๋ฅธ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ฐ™์€ ์œ„์น˜์˜ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ๋“ค์„ ๋‹ค์ค‘ ์ •์˜ํ•ด์„œ๋Š” ์•ˆ๋œ๋‹ค.

- ํด๋ผ์ด์–ธํŠธ์—๊ฒŒ ๋ถˆํ•„์š”ํ•œ ๋ชจํ˜ธํ•จ๋งŒ ์•ˆ๊ฒจ์ค€๋‹ค.

ex) ExecutorService์˜ submit ๋ฉ”์„œ๋“œ๋Š” Callable<T>๋ฅผ ๋ฐ›๋Š” ๊ฒƒ๊ณผ Runnable์„ ๋ฐ›๋Š” ๊ฒƒ์„ ๋‹ค์ค‘์ •์˜ํ–ˆ๋‹ค. ๊ทธ๋ž˜์„œ ์˜ฌ๋ฐ”๋ฅธ ๋ฉ”์„œ๋“œ๋ฅผ ์•Œ๋ ค์ฃผ๊ธฐ ์œ„ํ•ด ํ˜•๋ณ€ํ™˜ํ•ด์•ผ ํ•  ๋•Œ๊ฐ€ ์™•์™• ์ƒ๊ธด๋‹ค(์•„์ดํ…œ 52).

์•„์ดํ…œ 45. ์ŠคํŠธ๋ฆผ์€ ์ฃผ์˜ํ•ด์„œ ์‚ฌ์šฉํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•ด์•ผ ๋ฉ‹์ง€๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ด ์žˆ๊ณ , ๋ฐ˜๋ณต ๋ฐฉ์‹์ด ๋” ์•Œ๋งž์€ ์ผ๋„ ์žˆ๋‹ค.

ยท ๋งŽ์€ ์ž‘์—…๋“ค์ด ์ด ๋‘˜์„ ์กฐํ•ฉํ–ˆ์„ ๋•Œ ๊ฐ€์žฅ ๋ฉ‹์ง€๊ฒŒ ํ•ด๊ฒฐ๋œ๋‹ค.

ยท ์–ด๋Š ์ชฝ์„ ์„ ํƒํ•˜๋Š” ํ™•๊ณ ๋ถ€๋™ํ•œ ๊ทœ์น™์€ ์—†์ง€๋งŒ ์ฐธ๊ณ ํ•  ๋งŒํ•œ ์ง€์นจ ์ •๋„๋Š” ์žˆ๋‹ค.

ยท ์–ด๋Š ์ชฝ์ด ๋‚˜์€์ง€ ํ™•์—ฐํžˆ ๋“œ๋Ÿฌ๋‚˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ฒ ์ง€๋งŒ, ์•„๋‹ˆ๋”๋ผ๋„ ๋ฐฉ๋ฒ•์€ ์žˆ๋‹ค.

ยท ์–ด๋Š ์ชฝ์ด ๋‚˜์€์ง€ ํ™•์‹ ํ•˜๊ธฐ ์–ด๋ ต๋‹ค๋ฉด, ๋‘˜ ๋‹ค ํ•ด๋ณด๊ณ  ๋” ๋‚˜์€ ์ชฝ์„ ํƒํ•˜๋ผ.

์ŠคํŠธ๋ฆผ API์˜ ํ•ต์‹ฌ

ยท ์Šคํ”„๋ง API์˜ ๋ชฉ์ : ์ŠคํŠธ๋ง API๋Š” ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ž‘์—…(์ˆœ์ฐจ์ ์ด๋“  ๋ณ‘๋ ฌ์ ์ด๋“ )์„ ๋•๊ณ ์ž ์ž๋ฐ” 8์— ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

ยท ์ŠคํŠธ๋ฆผ API๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ถ”์ƒ ๊ฐœ๋… ์ค‘ ํ•ต์‹ฌ์€ ๋‘ ๊ฐ€์ง€๋‹ค.

1. ๋ฐ์ดํ„ฐ ์›์†Œ์˜ ์œ ํ•œ ๋˜๋Š” ๋ฌดํ•œ ์‹œํ€ธ์Šค(sequence)

2. ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ: ์ด ์›์†Œ๋“ค๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ์—ฐ์‚ฐ ๋‹จ๊ณ„๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ๊ฐœ๋…

- ์ŠคํŠธ๋ฆผ ์›์†Œ๋“ค์€ ์–ด๋””๋กœ๋ถ€ํ„ฐ๋“  ์˜ฌ ์ˆ˜ ์žˆ๋‹ค. ex) ์ปฌ๋ ‰์…˜, ๋ฐฐ์—ด, ํŒŒ์ผ, ์ •๊ทœํ‘œํ˜„์‹ ํŒจํ„ด ๋งค์ฒ˜, ๋‚œ์ˆ˜ ์ƒ์„ฑ๊ธฐ, ๋‹ค๋ฅธ ์ŠคํŠธ๋ฆผ

- ์ŠคํŠธ๋ฆผ ์•ˆ์˜ ๋ฐ์ดํ„ฐ ์›์†Œ๋“ค์€ ๊ฐ์ฒด ์ฐธ์กฐ๋‚˜ ๊ธฐ๋ณธ ํƒ€์ž… ๊ฐ’์ด๋‹ค. ๊ธฐ๋ณธ ํƒ€์ž… ๊ฐ’์œผ๋กœ int, long, double ์„ธ ๊ฐ€์ง€๋ฅผ ์ง€์›ํ•œ๋‹ค.

์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ

ยท ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์€ ์†Œ์Šค ์ŠคํŠธ๋ฆผ์—์„œ ์‹œ์ž‘ํ•ด ์ข…๋‹จ ์—ฐ์‚ฐ(terminal operation)์œผ๋กœ ๋๋‚˜๋ฉฐ, ๊ทธ ์‚ฌ์ด์— ํ•˜๋‚˜ ์ด์ƒ์˜ ์ค‘๊ฐ„ ์—ฐ์‚ฐ(intermediate operation)์ด ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค.

- ๊ฐ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์€ ์ŠคํŠธ๋ฆผ์„ ์–ด๋– ํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ณ€ํ™˜(transform)ํ•œ๋‹ค. ex) ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑ ๋ชปํ•˜๋Š” ์›์†Œ๋ฅผ ๊ฑธ๋Ÿฌ๋‚œ๋‹ค.

- ๋ณ€ํ™˜๋œ ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ ํƒ€์ž…์€ ๋ณ€ํ™˜ ์ „ ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ ํƒ€์ž…๊ณผ ๊ฐ™์€ ์ˆ˜๋„ ์žˆ๊ณ , ๋‹ค๋ฅผ ์ˆ˜๋„ ์žˆ๋‹ค.

- ์ข…๋‹จ ์—ฐ์‚ฐ์€ ๋งˆ์ง€๋ง‰ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์ด ๋‚ด๋†“์€ ์ŠคํŠธ๋ฆผ์— ์ตœํ›„์˜ ์—ฐ์‚ฐ์„ ๊ฐ€ํ•œ๋‹ค. ex) ์›์†Œ๋ฅผ ์ •๋ ฌํ•ด ์ปฌ๋ ‰์…˜์— ๋‹ด๊ฑฐ๋‚˜, ํŠน์ • ์›์†Œ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•˜๊ฑฐ๋‚˜, ๋ชจ๋“  ์›์†Œ๋ฅผ ์ถœ๋ จํ•˜๋Š” ์‹์ด๋‹ค.

ยท ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์€ ์ง€์—ฐ ํ‰๊ฐ€(lazy evaluation)๋œ๋‹ค.

- ํ‰๊ฐ€๋Š” ์ข…๋‹จ ์—ฐ์‚ฐ์ด ํ˜ธ์ถœ๋  ๋•Œ ์ด๋ค„์ง€๋ฉฐ, ์ข…๋‹จ ์—ฐ์‚ฐ์— ์“ฐ์ด์ง€ ์•Š๋Š” ๋ฐ์ดํ„ฐ ์›์†Œ๋Š” ๊ณ„์‚ฐ์— ์“ฐ์ด์ง€ ์•Š๋Š”๋‹ค.

- ์ง€์—ฐ ํ‰๊ฐ€๋Š” ๋ฌดํ•œ ์ŠคํŠธ๋ฆผ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ๋Š” ์—ด์‡ ๋‹ค.

์ฃผ์˜ ์‚ฌํ•ญ! ์ข…๋‹จ ์—ฐ์‚ฐ์„ ๋นผ๋จน์ง€ ๋ง์ž. ์ข…๋‹จ ์—ฐ์‚ฐ์ด ์—†๋Š” ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์€ ์•„๋ฌด ์ผ๋„ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

ยท ์ŠคํŠธ๋ฆผ API๋Š” ๋ฉ”์„œ๋“œ ์—ฐ์‡„๋ฅผ ์ง€์›ํ•˜๋Š” ํ”Œ๋ฃจ์–ธํŠธ API๋‹ค.

- ์ฆ‰, ํŒŒ์ดํ”„๋ผ์ธ ํ•˜๋‚˜๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ๋ชจ๋“  ํ˜ธ์ถœ์„ ์—ฐ๊ฒฐํ•˜์—ฌ ๋‹จ ํ•˜๋‚˜์˜ ํ‘œํ˜„์‹์œผ๋กœ ์™„์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

- ํŒŒ์ดํ”„๋ผ์ธ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ์—ฐ๊ฒฐํ•ด ํ‘œํ˜„์‹ ํ•˜๋‚˜๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

ยท ๊ธฐ๋ณธ์ ์œผ๋กœ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์€ ์ˆœ์ฐจ์ ์œผ๋กœ ์ˆ˜ํ–‰๋œ๋‹ค.

- ํŒŒ์ดํ”„๋ผ์ธ์„ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•˜๋ ค๋ฉด ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•˜๋Š” ์ŠคํŠธ๋ฆผ ์ค‘ ํ•˜๋‚˜์—์„œ parallel ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋œ๋‹ค.

ํ•˜์ง€๋งŒ ํšจ๊ณผ๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์€ ๋งŽ์ง€ ์•Š๋‹ค(์•„์ดํ…œ 48).

ยท ์ŠคํŠธ๋ฆผ API๋Š” ๋‹ค์žฌ๋‹ค๋Šฅํ•˜์—ฌ ์‚ฌ์‹ค์ƒ ์–ด๋– ํ•œ ๊ณ„์‚ฐ๋„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ŠคํŠธ๋ฆผ์˜ ๊ณผ์šฉ

ยท ์ŠคํŠธ๋ฆผ์„ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ์งง๊ณ  ๊น”๋”ํ•ด์ง€์ง€๋งŒ, ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ์ฝ๊ธฐ ์–ด๋ ต๊ณ  ์œ ์ง€๋ณด์ˆ˜๋„ ํž˜๋“ค์–ด์ง„๋‹ค.

์‚ฌ์ „ ํŒŒ์ผ์—์„œ ๋‹จ์–ด๋ฅผ ์ฝ์–ด ์‚ฌ์šฉ์ž๊ฐ€ ์ง€์ •ํ•œ ๋ฌธํ„ฑ๊ฐ’๋ณด๋‹ค ์›์†Œ ์ˆ˜๊ฐ€ ๋งŽ์€ ์•„๋‚˜๊ทธ๋žจ ๊ทธ๋ฃน์„ ์ถœ๋ ฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์‚ดํŽด๋ณด์ž.

- ์•„๋‚˜๊ทธ๋žจ: ์ฒ ์ž๋ฅผ ๊ตฌ์„ฑํ•˜๋Š” ์•ŒํŒŒ๋ฒณ์„ ๊ฐ™๊ณ  ์ˆœ์„œ๋งŒ ๋‹ค๋ฅธ ๋‹จ์–ด

ํ”„๋กœ๊ทธ๋žจ ์„ค๋ช…โ†“

๋”๋ณด๊ธฐ

// ์‚ฌ์ „ ํ•˜๋‚˜๋ฅผ ํ›‘์–ด ์›์†Œ ์ˆ˜๊ฐ€ ๋งŽ์€ ์•„๋‚˜๊ทธ๋žจ ๊ทธ๋ฃน๋“ค์„ ์ถœ๋ ฅํ•œ๋‹ค.
public class Anagrams {
    public static void main(String[] args) throws IOException {
        File dictionary = new File(args[0]);
        int minGroupSize = Integer.parseInt(args[1]);
        
        Map<String, Set<String>> groups = new HashMap<>();
            try (Scanner s = new Scanner(dictionary)) {
                while (s.hasNext()) {
                    String word = s.next();
                    groups.computeIfAbsent(alphabetize(word), (unused) -> new TreeSet<>()).add(word);
                }
            }
            
            for (Set<String> group : groups.values())
                if (group.size() >= minGroupSize)
                    System.out.println(group.size() + ": " + group);
                }
                
                private static String alphabetize(String s) {
                    char[] a = s.toCharArray();
                    Arrays.sort(a);
                    return new String(a);
                }
                }

ํ”„๋กœ๊ทธ๋žจ์˜ ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์—์„œ ๋งต์— ๊ฐ ๋‹จ์–ด๋ฅผ ์‚ฝ์ž…ํ•  ๋•Œ ์ž๋ฐ” 8์— ์ถ”๊ฐ€๋œ computeIfAbsent ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ ํ‚ค์™€ ๊ฐ’์„ ๋งคํ•‘ํ•ด๋†“๊ณ , ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

- computeIfAbsent: ๋งต ์•ˆ์— ํ‚ค๊ฐ€ ์žˆ๋Š”์ง€ ์ฐพ์€ ๋‹ค์Œ, ์žˆ์œผ๋ฉด ๊ทธ ํ‚ค์— ๋งคํ•‘๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ํ‚ค๊ฐ€ ์—†์œผ๋ฉด ๊ฑด๋„ค์ง„ ํ•จ์ˆ˜ ๊ฐ์ฒด๋ฅผ ํ‚ค์— ์ ์šฉํ•˜์—ฌ ๊ฐ’์„ ๊ณ„์‚ฐํ•ด๋‚ธ ๋‹ค์Œ ๊ทธ ํ‚ค์™€ ๊ฐ’์„ ๋งคํ•‘ํ•ด๋†“๊ณ , ๊ณ„์‚ฐ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋‹ค์Œ ํ”„๋กœ๊ทธ๋žจ์€ ์•ž์˜ ์ฝ”๋“œ์™€ ๊ฐ™์€ ์ผ์„ ํ•˜์ง€๋งŒ ์ŠคํŠธ๋ฆผ์„ ๊ณผํ•˜๊ฒŒ ํ™œ์šฉํ•œ๋‹ค.

- ์‚ฌ์ „ ํŒŒ์ผ์„ ์—ฌ๋Š” ๋ถ€๋ถ„๋งŒ ์ œ์™ธํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ ์ „์ฒด๊ฐ€ ๋‹จ ํ•˜๋‚˜์˜ ํ‘œํ˜„์‹์œผ๋กœ ์ฒ˜๋ฆฌ๋œ๋‹ค.

- ์งง์ง€๋งŒ ์ฝ๊ธฐ ์–ด๋ ต๋‹ค.

์ด์ฒ˜๋Ÿผ ์ŠคํŠธ๋ฆผ์„ ๊ณผ์šฉํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์ด ์ฝ๊ฑฐ๋‚˜ ์œ ์ง€๋ณด์ˆ˜ํ•˜๊ธฐ ์–ด๋ ค์›Œ์ง„๋‹ค.

// ์ŠคํŠธ๋ฆผ์„ ๊ณผํ•˜๊ฒŒ ์‚ฌ์šฉํ–ˆ๋‹ค - ๋”ฐ๋ผ ํ•˜์ง€ ๋ง ๊ฒƒ!
public class Anagrams {
    public static void main(String[] args) throws IOException {
        Path dictionary = Paths.get(args[0]);
        int minGroupSize = Integer.parseInt(args[1]);
        try (Stream<String> words = Files.lines(dictionary)) {
            words.collect(
                groupingBy(word -> word.chars().sorted()
                    .collect(StringBuilder::new,
                        (sb, c) -> sb.append((char) c),
                        StringBuilder::append).toString()))
                .values().stream()
                .filter(group -> group.size() >= minGroupSize)
                .map(group -> group.size() + ": " + group)
                .forEach(System.out::println);
        }
        }
        }

๋‹ค์Œ์€ ํ”„๋กœ๊ทธ๋žจ์€ ์•ž์„œ ๋‘ ํ”„๋กœ๊ทธ๋žจ๊ณผ ๊ฐ™์ง€๋งŒ ์ŠคํŠธ๋ฆผ์„ ์ ๋‹นํžˆ ์‚ฌ์šฉํ–ˆ๋‹ค. ๊ทธ ๊ฒฐ๊ณผ ์›๋ž˜ ์ฝ”๋“œ๋ณด๋‹ค ์งง์„ ๋ฟ ์•„๋‹ˆ๋ผ ๋ช…ํ™•ํ•˜๋‹ค.

// ์ŠคํŠธ๋ฆผ์„ ์ ์ ˆํžˆ ํ™œ์šฉํ•˜๋ฉด ๊น”๋”ํ•˜๊ณ  ๋ช…๋ฃŒํ•ด์ง„๋‹ค.
public class Anagrams {
    public static void main(String[] args) throws IOException {
        Path dictionary = Paths.get(args[0]);
        int minGroupSize = Integer.parseInt(args[1]);
        try (Stream<String> words = Files.lines(dictionary)) {
            words.collect(groupingBy(word -> alphabetize(word)))
                .values().stream()
                .filter(group -> group.size() >= minGroupSize)
                .forEach(g -> System.out.println(g.size() + ": " + g));
        }
        }
        
        // alphabetize ๋ฉ”์„œ๋“œ๋Š” ์ฝ”๋“œ ์ด์ „๊ณผ ๊ฐ™๋‹ค.
        }

alphabetize ๋ฉ”์„œ๋“œ๋„ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•ด ๋‹ค๋ฅด๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ๋ช…ํ™•์„ฑ์ด ๋–จ์–ด์ง€๊ณ  ์ž˜๋ชป ๊ตฌํ˜„ํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์ปค์ง„๋‹ค. ์‹ฌ์ง€์–ด ๋Š๋ ค์งˆ ์ˆ˜๋„ ์žˆ๋‹ค. ์ž๋ฐ”๊ฐ€ ๊ธฐ๋ณธ ํƒ€์ž…์ธ char์šฉ ์ŠคํŠธ๋ฆผ์„ ์ง€์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ยท ๋žŒ๋‹ค ๋งค๊ฐœ๋ณ€์ˆ˜์˜ ์ด๋ฆ„์€ ์ฃผ์˜ํ•ด์„œ ์ •ํ•˜์ž.

- ๋žŒ๋‹ค์—์„œ๋Š” ํƒ€์ž… ์ด๋ฆ„์„ ์ž์ฃผ ์ƒ๋žตํ•˜๋ฏ€๋กœ ๋งค๊ฐœ๋ณ€์ˆ˜ ์ด๋ฆ„์„ ์ž˜ ์ง€์–ด์•ผ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์˜ ๊ฐ€๋™์„ฑ์ด ์œ ์ง€๋œ๋‹ค.

- ์•ž ์ฝ”๋“œ์—์„œ ๋งค๊ฐœ๋ณ€์ˆ˜ g๋Š” ์‚ฌ์‹ค group์ด ๋ผ๊ณ  ํ•˜๋Š”๊ฒŒ ๋‚ซ๋‹ค.

ยท ๋„์šฐ๋ฏธ ๋ฉ”์„œ๋“œ๋ฅผ ์ ์ ˆํžˆ ํ™œ์šฉํ•˜๋Š” ์ผ์˜ ์ค‘์š”์„ฑ์€ ์ผ๋ฐ˜ ๋ฐ˜๋ณต ์ฝ”๋“œ์—์„œ๋ณด๋‹ค๋Š” ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ํ›จ์”ฌ ํฌ๋‹ค.

- ํŒŒ์ดํ”„๋ผ์ธ์—์„œ๋Š” ํƒ€๋ฆฝ ์ •๋ณด๊ฐ€ ๋ช…์‹œ ๋˜์ง€ ์•Š๊ฑฐ๋‚˜ ์ž„์‹œ ๋ณ€์ˆ˜๋ฅผ ์ž์ฃผ ์‚ฌ์šฉํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

- ์œ„ ์ฝ”๋“œ์—์„œ๋Š” ๋‹จ์–ด์˜ ์ฒ ์ž๋ฅผ ์•ŒํŒŒ๋ฒณ์ˆœ์œผ๋กœ ์ •๋ ฌํ•˜๋Š” ์ผ์„ ๋ณ„๋„ ๋ฉ”์„œ๋“œ์ธ alphabetize์—์„œ ์ˆ˜ํ–‰ํ–ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ์—ฐ์‚ฐ์— ์ ์ ˆํ•œ ์ด๋ฆ„์„ ์ง€์–ด์ฃผ๊ณ , ์„ธ๋ถ€ ๊ตฌํ˜„์„ ์ฃผ ํ”„๋กœ๊ทธ๋žจ ๋กœ์ง ๋ฐ–์œผ๋กœ ๋นผ๋‚ด ์ „์ฒด์ ์ธ ๊ฐ€๋…์„ฑ์„ ๋†’์ธ๋‹ค.

ยท ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์€ ๋˜ํ’€์ด๋˜๋Š” ๊ณ„์‚ฐ์„ ํ•จ์ˆ˜ ๊ฐ์ฒด๋กœ ํ‘œํ˜„ํ–ˆ๊ณ , ๋ฐ˜๋ณต ์ฝ”๋“œ์—์„œ๋Š” ์ฝ”๋“œ ๋ธ”๋ก์„ ์‚ฌ์šฉํ•ด ํ‘œํ˜„ํ–ˆ๋‹ค.

์ŠคํŠธ๋ฆผ๊ณผ char

๋‹ค์Œ์€ char ๊ฐ’๋“ค์„ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ๋‹ค.

"Hello world!".chars().forEach(System.out::print);

์œ„ ์ฝ”๋“œ๋Š” Hello world!๋ฅผ ์ถœ๋ ฅํ•˜๋ฆฌ๋ผ ๊ธฐ๋Œ€๋˜์ง€๋งŒ, 721011081081113211911111410810033์„ ์ถœ๋ ฅํ•œ๋‹ค.

"Hello world!".chars()๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ๋Š” char๊ฐ€ ์•„๋‹Œ int ๊ฐ’์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์ด์ฒ˜๋Ÿผ ์ด๋ฆ„์ด chars์ธ๋ฐ int ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ์žˆ๋‹ค. ์˜ฌ๋ฐ”๋ฅธ print ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ฒŒ ํ•˜๋ ค๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ํ˜•๋ณ€ํ™˜์„ ๋ช…์‹œ์ ์œผ๋กœ ํ•ด์ค˜์•ผํ•œ๋‹ค.

ยท ํ•˜์ง€๋งŒ char ๊ฐ’๋“ค์„ ์ฒ˜๋ฆฌํ•  ๋•Œ๋Š” ์ŠคํŠธ๋ฆผ์„ ์‚ผ๊ฐ€๋Š” ํŽธ์ด ๋‚ซ๋‹ค.

์ŠคํŠธ๋ฆผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ

ยท ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒŒ ๊ฐ€๋Šฅํ•ด๋„ ์ฝ”๋“œ ๊ฐ€๋…์„ฑ๊ณผ ์œ ์ง€๋ณด์ˆ˜ ์ธก๋ฉด์—์„œ ์†ํ•ด ๋ณผ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ์ฃผ์˜ํ•˜์ž.

ยท ์ŠคํŠธ๋ฆผ๊ณผ ๋ฐ˜๋ณต๋ฌธ์„ ์ ์ ˆํžˆ ์กฐํ•ฉํ•˜๋Š” ๊ฒŒ ์ตœ์„ ์ด๋‹ค.

ยท ๊ธฐ์กด ์ฝ”๋“œ๋Š” ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋„๋ก ๋ฆฌํŒฉํ„ฐ๋งํ•˜๋˜, ์ƒˆ ์ฝ”๋“œ๊ฐ€ ๋” ๋‚˜์•„ ๋ณด์ผ ๋•Œ๋งŒ ๋ฐ˜์˜ํ•˜์ž.

์ฝ”๋“œ๋ธ”๋Ÿญ์— ์•ˆ์„ฑ๋งž์ถค์ธ ์ผ

ยท ํ•จ์ˆ˜ ๊ฐ์ฒด๋กœ๋Š” ํ•  ์ˆ˜ ์—†์ง€๋งŒ, ์ฝ”๋“œ ๋ธ”๋ก์œผ๋กœ๋Š” ํ•  ์ˆ˜ ์žˆ๋Š” ์ผ๋“ค์ด๋‹ค.

1. ์ฝ”๋“œ ๋ธ”๋ก์—์„œ๋Š” ๋ฒ”์œ„ ์•ˆ์˜ ์ง€์—ญ๋ณ€์ˆ˜๋ฅผ ์ฝ๊ณ  ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋žŒ๋‹ค์—์„œ๋Š” final์ด๊ฑฐ๋‚˜ ์‚ฌ์‹ค์ƒ final์ธ ๋ณ€์ˆ˜๋งŒ ์ฝ์„ ์ˆ˜ ์žˆ๊ณ , ์ง€์—ญ๋ณ€์ˆ˜๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๊ฑด ๋ถˆ๊ฐ€๋Šฅํ•˜๋‹ค.

2. ์ฝ”๋“œ ๋ธ”๋ก์—์„œ๋Š” return ๋ฌธ์„ ์‚ฌ์šฉํ•ด ๋ฉ”์„œ๋“œ์—์„œ ๋น ์ ธ๋‚˜๊ฐ€๊ฑฐ๋‚˜, break๋‚˜ continue ๋ฌธ์œผ๋กœ ๋ธ”๋ก ๋ฐ”๊นฅ์˜ ๋ฐ˜๋ณต๋ฌธ์„ ์ข…๋ฃŒํ•˜๊ฑฐ๋‚˜ ๋ฐ˜๋ณต์„ ํ•œ ๋ฒˆ ๊ฑด๋„ˆ๋›ธ ์ˆ˜ ์žˆ๋‹ค. ๋˜ํ•œ ๋ฉ”์„œ๋“œ ์„ ์–ธ์— ๋ช…์‹œ๋œ ๊ฒ€์‚ฌ ์˜ˆ์™ธ๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ๋‹ค. ๋žŒ๋‹ค๋กœ๋Š” ์ด์ค‘ ์–ด๋–ค ๊ฒƒ๋„ ํ•  ์ˆ˜ ์—†๋‹ค.

์ŠคํŠธ๋ฆผ์— ์•ˆ์„ฑ๋งž์ถค์ธ ์ผ

ยท ์ด ์ค‘ ํ•˜๋‚˜๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” ๋กœ์ง์ด๋ผ๋ฉด, ์ŠคํŠธ๋ฆผ์„ ์ ์šฉํ•˜๊ธฐ ์ข‹์€ ํ›„๋ณด๋‹ค.

1. ์›์†Œ๋“ค์˜ ์‹œํ€ธ์Šค๋ฅผ ์ผ๊ด€๋˜๊ฒŒ ๋ณ€ํ™˜ํ•œ๋‹ค.

2. ์›์†Œ๋“ค์˜ ์‹œํ€ธ์Šค๋ฅผ ํ•„ํ„ฐ๋งํ•œ๋‹ค.

3. ์›์†Œ๋“ค์˜ ์‹œํ€ธ์Šค๋ฅผ ํ•˜๋‚˜์˜ ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•ด ๊ฒฐํ•ฉํ•œ๋‹ค. ex) ๋”ํ•˜๊ธฐ, ์—ฐ๊ฒฐํ•˜๊ธฐ, ์ตœ์†Ÿ๊ฐ’ ๊ตฌํ•˜๊ธฐ ๋“ฑ

4. ์›์†Œ๋“ค์˜ ์‹œํ€ธ์Šค๋ฅผ ์ปฌ๋ ‰์…˜์— ๋ชจ์€๋‹ค(์•„๋งˆ๋„ ๊ณตํ†ต๋œ ์†์„ฑ์„ ๊ธฐ์ค€์œผ๋กœ ๋ฌถ์–ด๊ฐ€๋ฉฐ).

5. ์›์†Œ๋“ค์˜ ์‹œํ€ธ์Šค์—์„œ ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์›์†Œ๋ฅผ ์ฐพ๋Š”๋‹ค.

์ŠคํŠธ๋ฆผ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์–ด๋ ค์šด ์ผ

ยท ๋Œ€ํ‘œ์ ์ธ ์˜ˆ: ํ•œ ๋ฐ์ดํ„ฐ๊ฐ€ ํŒŒ์ดํ”„๋ผ์ธ์˜ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„๋ฅผ ํ†ต๊ณผํ•  ๋•Œ ์ด ๋ฐ์ดํ„ฐ์˜ ๊ฐ ๋‹จ๊ณ„์—์„œ ๊ฐ’๋“ค์„ ๋™์‹œ์— ์ ‘๊ทผํ•˜๊ธฐ ์–ด๋ ค์šด ๊ฒฝ์šฐ

- ์›์ธ: ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์€ ์ผ๋‹จ ํ•œ ๊ฐ’์„ ๋‹ค๋ฅธ ๊ฐ’์— ๋งคํ•‘ํ•˜๊ณ  ๋‚˜๋ฉด ์›๋ž˜์˜ ๊ฐ’์€ ์ฝ๋Š” ๊ตฌ์กฐ์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

์›๋ž˜ ๊ฐ’๊ณผ ์ƒˆ๋กœ์šด ๊ฐ’์˜ ์Œ์„ ์ €์žฅํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•ด ๋งคํ•‘ํ•˜๋Š” ์šฐํšŒ ๋ฐฉ๋ฒ•๋„ ์žˆ์ง€๋งŒ, ๋งŒ์กฑ์Šค๋Ÿฌ์šด ํ•ด๋ฒ•์€ ์•„๋‹ˆ๋‹ค. ํŠนํžˆ ๋งคํ•‘ ๊ฐ์ฒด๊ฐ€ ํ•„์š”ํ•œ ๋‹จ๊ณ„๊ฐ€ ์—ฌ๋Ÿฌ ๊ณณ์ด๋ฉด ๋” ๊ทธ๋ ‡๋‹ค.

- ์ด๋Ÿฐ ๋ฐฉ์‹์€ ์ฝ”๋“œ ์–‘๋„ ๋งŽ๊ณ  ์ง€์ €๋ถ„ํ•˜์—ฌ ์ŠคํŠธ๋ฆผ์„ ์“ฐ๋Š” ์ฃผ๋ชฉ์ ์—์„œ ๋ฒ—์–ด๋‚œ๋‹ค.

๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ๋ผ๋ฉด, ์•ž ๋‹จ๊ณ„์˜ ๊ฐ’์ด ํ•„์š”ํ•  ๋•Œ ๋งคํ•‘์„ ๊ฑฐ๊พธ๋กœ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋‚ซ๋‹ค.

์ฒ˜์Œ 20๊ฐœ์˜ ๋ฉ”๋ฅด์„ผ ์†Œ์ˆ˜๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ์ž‘์„ฑํ•ด๋ณด์ž. ๋ฉ”๋ฅด์„ผ ์ˆ˜๋Š” 2^p - 1 ํ˜•ํƒœ์˜ ์ˆ˜๋‹ค. p๊ฐ€ ์†Œ์ˆ˜๋ฉด, ํ•ด๋‹น ๋ฉ”์„œ์„ผ ์ˆ˜๋„ ์†Œ์ˆ˜์ผ ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ด๋ฅผ ๋ฉ”๋ฅด์„ผ ์†Œ์ˆ˜๋ผ ํ•œ๋‹ค. ์ด ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ฒซ ์ŠคํŠธ๋ฆผ์œผ๋กœ๋Š” ๋ชจ๋“  ์†Œ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ๊ฒƒ์ด๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ๋Š” ๋ฌดํ•œ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋‹ค. BigInteger์˜ ์ •์  ๋ฉค๋ฒ„๋“ค์€ ์ •์  ์ž„ํฌํŠธํ•˜์—ฌ ์‚ฌ์šฉํ•œ๋‹ค.

static Stream<BigInteger> primes(){
    return Stream.iterate(TWO, BigInteger::nextProbablePrime);
}

๋ฉ”์„œ๋“œ ์ด๋ฆ„ primes๋Š” ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ๊ฐ€ ์†Œ์ˆ˜์ž„์„ ๋งํ•ด์ค€๋‹ค.

- ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ ์ด๋ฆ„์€ ์ด์ฒ˜๋Ÿผ ์›์†Œ์˜ ์ •์ฒด๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๋ณต์ˆ˜ ๋ช…์‚ฌ๋กœ ์“ฐ๊ธฐ๋ฅผ ์ถ”์ฒœํ•œ๋‹ค. ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์˜ ๊ฐ€๋…์„ฑ์ด ํฌ๊ฒŒ ์ข‹์•„์งˆ ๊ฒƒ์ด๋‹ค.

Stream.iterate๋ผ๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ๋Š” ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ 2๊ฐœ ๋ฐ›๋Š”๋‹ค. ์ฒซ ๋ฒˆ์งธ๋Š” ์ŠคํŠธ๋ฆผ์˜ ์ฒซ ๋ฒˆ์งธ ์›์†Œ๊ณ , ๋‘ ๋ฒˆ์งธ๋Š” ์ŠคํŠธ๋ฆผ์—์„œ ๋‹ค์Œ ์›์†Œ๋ฅผ ์ƒ์„ฑํ•ด์ฃผ๋Š” ํ•จ์ˆ˜๋‹ค.

๋‹ค์Œ์€ ์ฒ˜์Œ 20๊ฐœ์˜ ๋ฉ”๋ฅด์„ผ ์†Œ์ˆ˜๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค. ์†Œ์ˆ˜๋“ค์„ ์‚ฌ์šฉํ•ด ๋ฉ”๋ฅด์„ผ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๊ณ , ๊ฒฐ๊ณผ๊ฐ’์ด ์†Œ์ˆ˜์ธ ๊ฒฝ์šฐ๋งŒ ๋‚จ๊ธฐ๊ณ , ๊ฒฐ๊ณผ ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ ์ˆ˜๋ฅผ 20๊ฐœ๋กœ ์ œํ•œํ•˜๊ณ , ์ž‘์—…์ด ๋๋‚˜๋ฉด ๊ฒฐ๊ณผ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

- ๋งค์ง๋„˜๋ฒ„ 50์€ ์†Œ์ˆ˜์„ฑ ๊ฒ€์‚ฌ๊ฐ€ true๋ฅผ ๋ฐ˜ํ™˜ํ•  ํ™•๋ฅ ์„ ์ œ์–ดํ•œ๋‹ค.

public static void main(String[] args){
    primes().map(p -> TWO.pow(p.intValueExact()).subtract(ONE))
        .filter(mersenne -> mersenne.isProbablePrime(50))
        .limit(20)
        .forEach(System.out :: println);
}

๊ฐ ๋ฉ”๋ฅด์„ผ ์†Œ์ˆ˜์˜ ์•ž ์ง€์ˆ˜(p)๋ฅผ ์ถœ๋ ฅํ•˜๊ธธ ์›ํ•œ์ž๊ณ  ํ•ด๋ณด์ž. ์ฒซ ๋ฒˆ์งธ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์—์„œ ์ˆ˜ํ–‰ํ•œ ๋งคํ•‘์„ ๊ฑฐ๊พธ๋กœ ์ˆ˜ํ–‰ํ•ด ๋ฉ”๋ฅด์„ผ ์ˆ˜์˜ ์ง€์ˆ˜๋ฅผ ์‰ฝ๊ฒŒ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

์ง€์ˆ˜๋Š” ๋‹จ์ˆœํžˆ ์ˆซ์ž๋ฅผ ์ด์ง„์ˆ˜๋กœ ํ‘œํ˜„ํ•œ ๋‹ค์Œ ๋ช‡ ๋น„ํŠธ์ธ์ง€ ์„ธ๋ฉด ๋‚˜์˜ค๋ฏ€๋กœ, ์ข…๋‹จ ์—ฐ์‚ฐ์„ ๋‹ค์Œ์ฒ˜๋Ÿผ ์ž‘์„ฑํ•˜๋ฉด ์›ํ•˜๋Š” ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

    .forEach(mp -> System.out.println(mp.bitLength() + " : " + mp));

์ŠคํŠธ๋ฆผ๊ณผ ๋ฐ˜๋ณต ์ค‘ ์–ด๋Š ์ชฝ์„ ์จ์•ผ ํ• ์ง€ ๋ฐ”๋กœ ์•Œ๊ธฐ ์–ด๋ ค์šด ์ž‘์—…

์ด๋Ÿฌํ•œ ์ž‘์—…์˜ ์˜ˆ๋กœ ์นด๋“œ ๋ฑ์„ ์ดˆ๊ธฐํ™”ํ•˜๋Š” ์ž‘์—…์„ ์ƒ๊ฐํ•ด๋ณด์ž. ์นด๋“œ๋Š” ์ˆซ์ž(rank)์™€ ๋ฌด๋Šฌ(suit)์„ ๋ฌถ์€ ๋ถˆ๋ณ€ ๊ฐ’ ํด๋ž˜์Šค์ด๊ณ , ์ˆซ์ž์™€ ๋ฌด๋Šฌ๋Š” ๋ชจ๋‘ ์—ด๊ฑฐ ํƒ€์ž…์ด๋‹ค.

์ด ์ž‘์—…์€ ๋‘ ์ง‘ํ•ฉ์˜ ์›์†Œ๋“ค๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์กฐํ•ฉ์„ ๊ณ„์‚ฐํ•˜๋Š” ๋ฌธ์ œ๋‹ค. ์ˆ˜ํ•™์ž๋“ค์€ ์ด๋ฅผ ๋‘ ์ง‘ํ•ฉ ๋ฐ์นด๋ฅดํŠธ ๊ณฑ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

๋‹ค์Œ์€ for-each ๋ฐ˜๋ณต๋ฌธ์„ ์ค‘์ฒฉํ•ด ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๋‹ค.

private static List<Card> newDeck(){
    List<Card> result = new ArrayList<>();
        for(Suit suit : Suit.values())
            for(Rank rank : Rank.values())
                result.add(new Card(suit, rank));
        return result;
        }

๋‹ค์Œ์€ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๊ตฌํ˜„ํ•œ ์ฝ”๋“œ๋‹ค. ์ค‘๊ฐ„ ์—ฐ์‚ฐ์œผ๋กœ ์‚ฌ์šฉํ•œ flatMap์€ ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ ๊ฐ๊ฐ์„ ํ•˜๋‚˜์˜ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋งคํ•‘ํ•œ ๋‹ค์Œ, ๊ทธ ์ŠคํŠธ๋ฆผ๋“ค์„ ๋‹ค์‹œ ํ•˜๋‚˜์˜ ์ŠคํŠธ๋ฆผ์œผ๋กœ ํ•ฉ์นœ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ์ค‘์ฒฉ๋œ ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค.

- ์ด๋ฅผ ํ‰ํƒ„ํ™”(flattening)์ด๋ผ๊ณ  ํ•œ๋‹ค.

private static List<Card> newDeck(){
    return Stream.of(Suit.values())
        .flatMap(suit ->
            Stream.of(Rank.values())
                .map(rank -> new Card(suit, rank)))
                .collect(toList());
            }

ยท ์ด๋Ÿฌํ•œ ๋‘ ์ฝ”๋“œ๋Š” ๊ฐœ์ธ์˜ ์ทจํ–ฅ๊ณผ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํ™˜๊ฒฝ์˜ ๋ฌธ์ œ๋‹ค.

- ์ดํ•ดํ•˜๊ณ  ์œ ์ง€ ๋ณด์ˆ˜ํ•˜๊ธฐ์— ์ฒ˜์Œ ์ฝ”๋“œ๊ฐ€ ๋” ํŽธํ•œ ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ๋งŽ์„ ๊ฒƒ์ด๋‹ค.

- ์ŠคํŠธ๋ฆผ ๋ฐฉ์‹์ด ๋‚˜์•„ ๋ณด์ด๊ณ , ๋™๋ฃŒ๋“ค๋„ ์ŠคํŠธ๋ฆผ ์ฝ”๋“œ๋ฅผ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๊ณ  ์„ ํ˜ธํ•œ๋‹ค๋ฉด ์ŠคํŠธ๋ฆผ ๋ฐฉ์‹์„ ์‚ฌ์šฉํ•˜์ž.

- ํ™•์‹ ์ด ์„œ์ง€ ์•Š๋Š”๋‹ค๋ฉด, ์ฒซ ๋ฒˆ์งธ ๋ฐฉ์‹์„ ์“ฐ๋Š” ๊ฒŒ ์•ˆ์ „ํ•  ๊ฒƒ์ด๋‹ค.

์•„์ดํ…œ 46. ์ŠคํŠธ๋ฆผ์—์„œ๋Š” ๋ถ€์ž‘์šฉ ์—†๋Š” ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ์Šคํ”„๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ํ•ต์‹ฌ์€ ๋ถ€์ž‘์šฉ ์—†๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด์— ์žˆ๋‹ค.

ยท ์ŠคํŠธ๋ฆผ๋ฟ ์•„๋‹ˆ๋ผ ์ŠคํŠธ๋ฆผ ๊ด€๋ จ ๊ฐ์ฒด์— ๊ฑด๋„ค์ง€๋Š” ๋ชจ๋“  ํ•จ์ˆ˜ ๊ฐ์ฒด๊ฐ€ ๋ถ€์ž‘์šฉ์ด ์—†์–ด์•ผ ํ•œ๋‹ค.

ยท ์ข…๋‹จ ์—ฐ์‚ฐ ์ค‘ forEach๋Š” ์ŠคํŠธ๋ฆผ์ด ์ˆ˜ํ–‰ํ•œ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ•  ๋•Œ๋งŒ ์ด์šฉํ•ด์•ผ ํ•œ๋‹ค. ๊ณ„์‚ฐ ์ž์ฒด์—๋Š” ์ด์šฉํ•˜์ง€ ๋ง์ž.

ยท ์ŠคํŠธ๋ฆผ์„ ์˜ฌ๋ฐ”๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์ˆ˜์ง‘๊ธฐ๋ฅผ ์ž˜ ์•Œ์•„๋‘ฌ์•ผ ํ•œ๋‹ค.

- ๊ฐ€์žฅ ์ค‘์š”ํ•œ ์ˆ˜์ง‘๊ธฐ ํŒฉํ„ฐ๋ฆฌ๋Š” toList, toSet, toMap, groupingBy, joining์ด๋‹ค.

์ŠคํŠธ๋ฆผ API์˜ ํŠน์ง•

ยท ์Šคํ”„๋ฆผ์€ ๊ทธ์ € ๋˜ ํ•˜๋‚˜์˜ API๊ฐ€ ์•„๋‹Œ, ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๊ธฐ์ดˆํ•œ ํŒจ๋Ÿฌ๋‹ค์ž„์ด๋‹ค.

- ์ŠคํŠธ๋ฆผ์ด ์ œ๊ณตํ•˜๋Š” ํ‘œํ˜„๋ ฅ, ์†๋„, ๋ณ‘๋ ฌ์„ฑ์„ ์–ป์œผ๋ ค๋ฉด API ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์ด ํŒจ๋Ÿฌ๋‹ค์ž„๊นŒ์ง€ ํ•จ๊ป˜ ๋ฐ›์•„๋“ค์—ฌ์•ผ ํ•œ๋‹ค.

ยท ์ŠคํŠธ๋ฆผ ํŒจ๋Ÿฌ๋‹ค์ž„์˜ ํ•ต์‹ฌ์€ ๊ณ„์‚ฐ์„ ์ผ๋ จ์˜ ๋ณ€ํ™˜์œผ๋กœ ์žฌ๊ตฌ์„ฑ ํ•˜๋Š” ๋ถ€๋ถ„์ด๋‹ค. ์ด๋•Œ ๊ฐ ๋ณ€ํ™˜ ๋‹จ๊ณ„๋Š” ๊ฐ€๋Šฅํ•œ ์ด์ „ ๋‹จ๊ณ„์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ›์•„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ˆœ์ˆ˜ ํ•จ์ˆ˜์—ฌ์•ผ ํ•œ๋‹ค.

- ์ด๋ ‡๊ฒŒ ํ•˜๋ ค๋ฉด ์ค‘๊ฐ„ ๋‹จ๊ณ„๋“  ์ข…๋‹จ ๋‹จ๊ณ„๋“  ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ์— ๊ฑด๋„ค๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด๋Š” ๋ชจ๋‘ ๋ถ€์ž‘์šฉ(side effect)์ด ์—†์–ด์•ผ ํ•œ๋‹ค.

- ์ˆœ์ˆ˜ ํ•จ์ˆ˜: ์˜ค์ง ์ž…๋ ฅ๋งŒ์ด ๊ฒฐ๊ณผ์— ์˜ํ–ฅ์„ ์ฃผ๋Š” ํ•จ์ˆ˜๋‹ค. ๋‹ค๋ฅธ ๊ฐ€๋ณ€ ์ƒํƒœ๋ฅผ ์ฐธ์กฐํ•˜์ง€ ์•Š๊ณ , ํ•จ์ˆ˜ ์Šค์Šค๋กœ๋„ ๋‹ค๋ฅธ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค.

์ŠคํŠธ๋ฆผ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ ์˜ˆ์‹œ

๋‹ค์Œ์€ ํ…์ŠคํŠธ ํŒŒ์ผ์—์„œ ๋‹จ์–ด๋ณ„ ์ˆ˜๋ฅผ ์„ธ์–ด ๋นˆ๋„ํ‘œ๋กœ ๋งŒ๋“œ๋Š” ํ”„๋กœ๊ทธ๋žจ์ด๋‹ค.

// ์ŠคํŠธ๋ฆผ ํŒจ๋Ÿฌ๋‹ค์ž„์„ ์ดํ•ดํ•˜์ง€ ๋ชปํ•œ ์ฑ„ API๋งŒ ์‚ฌ์šฉํ–ˆ๋‹ค - ๋”ฐ๋ผ ํ•˜์ง€ ๋ง ๊ฒƒ!
Map<String, Long> freq = new HashMap<>();
    try(
        Stream<String> words = new Scanner(file).tokens())
            words.forEach(word -> {
                freq.merge(word.toLowerCase(), 1L, Long::sum);
            });
            }

์ŠคํŠธ๋ฆผ, ๋žŒ๋‹ค, ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ–ˆ๊ณ , ๊ฒฐ๊ณผ๋„ ์˜ฌ๋ฐ”๋ฅด์ง€๋งŒ ์ŠคํŠธ๋ฆผ ์ฝ”๋“œ๋ผ ํ•  ์ˆ˜ ์—†๋‹ค. ์ŠคํŠธ๋ฆผ ์ฝ”๋“œ๋ฅผ ๊ฐ€์žฅํ•œ ๋ฐ˜๋ณต์ฝ”๋“œ๋‹ค.

- ์ŠคํŠธ๋ฆผ API์˜ ์ด์ ์„ ์‚ด๋ฆฌ์ง€ ๋ชปํ•˜์—ฌ ๊ฐ™์€ ๊ธฐ๋Šฅ์˜ ๋ฐ˜๋ณต์  ์ฝ”๋“œ๋ณด๋‹ค ๊ธธ๊ณ , ์–ด๋ ต๊ณ , ์œ ์ง€๋ณด์ˆ˜์—๋„ ์ข‹์ง€ ์•Š๋‹ค.

ยท ๋ฌธ์ œ์ : forEach์—์„œ ์™ธ๋ถ€ ์ƒํƒœ(๋นˆ๋„ํ‘œ)๋ฅผ ์ˆ˜์ •ํ•˜๋Š” ๋žŒ๋‹ค๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.

์ŠคํŠธ๋ฆผ์„ ์ œ๋Œ€๋กœ ํ™œ์šฉํ•œ ์˜ˆ์‹œ

๋‹ค์Œ์€ ์œ„ ์ฝ”๋“œ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ˆ˜์ •ํ•œ ๋ชจ์Šต์ด๋‹ค.

Map<String, Long> freq;
    try (Stream<String> words = new Scanner(file).tokens()) {
        freq = words.collect(groupingBy(String::toLowerCase, counting()));
    }

ยท ์ด์ „ ์ฝ”๋“œ์™€ ๊ฐ™์€ ์ผ์„ ํ•˜์ง€๋งŒ, ์ด๋ฒˆ์—” ์ŠคํŠธ๋ฆผ API๋ฅผ ์ œ๋Œ€๋กœ ์‚ฌ์šฉํ–ˆ๊ณ , ์งง๊ณ  ๋ช…ํ™•ํ•˜๋‹ค.

ยท forEach ์—ฐ์‚ฐ์€ ์ŠคํŠธ๋ฆผ ๊ณ„์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ ํ•  ๋•Œ๋งŒ ์‚ฌ์šฉํ•˜๊ณ , ๊ณ„์‚ฐํ•˜๋Š” ๋ฐ๋Š” ์“ฐ์ง€ ๋ง์ž.

- forEach ์—ฐ์‚ฐ์€ ์ข…๋‹จ ์—ฐ์‚ฐ ์ค‘ ๊ธฐ๋Šฅ์ด ๊ฐ€์žฅ ์ ๊ณ , ๊ฐ€์žฅ '๋œ' ์ŠคํŠธ๋ฆผ๋‹ต๋‹ค. ๋Œ€๋†“๊ณ  ๋ฐ˜๋ณธ์ ์ด์–ด์„œ ๋ณ‘๋ ฌํ™”ํ•  ์ˆ˜๋„ ์—†๋‹ค.

ยท Scanner์˜ ์ŠคํŠธ๋ฆผ ๋ฉ”์„œ๋“œ์ธ tokens๋ฅผ ์‚ฌ์šฉํ•ด ์ŠคํŠธ๋ฆผ์„ ์–ป์—ˆ๋‹ค.

- ์ž๋ฐ” 9๋ถ€ํ„ฐ ์ง€์›ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋กœ, ๊ทธ ์ด์ „ ๋ฒ„์ „์„ ์“ฐ๋Š” ์‚ฌ๋žŒ์€ ์–ด๋Œ‘ํ„ฐ๋ฅผ ์ด์šฉํ•˜์—ฌ (Iterator๋ฅผ ๊ตฌํ˜„ํ•œ) Scanner๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„์ดํ…œ 47์—์„œ ์‚ฌ์šฉ๋˜๋Š” streamOf(Iterable<E>)๊ฐ€ ์ข‹์€ ์˜ˆ๋‹ค.

์ŠคํŠธ๋ฆผ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ์ˆ  - ์ˆ˜์ง‘๊ธฐ(collector)

ยท ์œ„ ์ฝ”๋“œ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ์ˆ˜์ง‘๊ธฐ(collector)๋Š” ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๊ผญ ๋ฐฐ์›Œ์•ผํ•˜๋Š” ๊ฐœ๋…์ด๋‹ค.

- ์ˆ˜์ง‘๊ธฐ๊ฐ€ ์ƒ์„ฑํ•˜๋Š” ๊ฐ์ฒด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ ์ปฌ๋ ‰์…˜์ด๋ฉฐ, ๊ทธ๋ž˜์„œ "collector"๋ผ๋Š” ์ด๋ฆ„์„ ์“ด๋‹ค.

ยท java.util.Collectors ํด๋ž˜์Šค๋Š” ๋ฉ”์„œ๋“œ๋ฅผ 39๊ฐœ๋‚˜ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ , ํƒ€์ž… ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ 5๊ฐœ๋‚˜ ๋˜์ง€๋งŒ, ๋ณต์žกํ•œ ์„ธ๋ถ€ ๋‚ด์šฉ์„ ์ž˜ ๋ชฐ๋ผ๋„ ์ด API์˜ ์žฅ์ ์„ ๋Œ€๋ถ€๋ถ„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

- Collector ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ถ•์†Œ(reduction) ์ „๋žต์„ ์บก์Šํ™”ํ•œ ๋ธ”๋ž™๋ฐ•์Šค ๊ฐ์ฒด๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

- ์ถ•์†Œ: ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ๋“ค์„ ๊ฐ์ฒด ํ•˜๋‚˜์— ์ทจํ•ฉํ•œ๋‹ค๋Š” ๋œป

์ปฌ๋ ‰์…˜๊ณผ ์ŠคํŠธ๋ฆผ

ยท ์ˆ˜์ง‘๊ธฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ๋ฅผ ์†์‰ฝ๊ฒŒ ์ปฌ๋ ‰์…˜์œผ๋กœ ๋ชจ์„ ์ˆ˜ ์žˆ๋‹ค.

ยท ํ•ด๋‹น ๊ธฐ๋Šฅ์„ ํ•˜๋Š” ์ˆ˜์ง‘๊ธฐ๋Š” ์ด ์„ธ ๊ฐ€์ง€๋กœ toList(), toSet(), toCollection(collectionFactory)๊ฐ€ ๊ทธ ์ฃผ์ธ๊ณต์ด๋‹ค.

- ์ด๋“ค์€ ์ฐจ๋ก€๋กœ ๋ฆฌ์ŠคํŠธ, ์ง‘ํ•ฉ, ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ง€์ •ํ•œ ์ปฌ๋ ‰์…˜ ํƒ€์ž…์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์•ž์„œ ๋ฐฐ์šด ์ง€์‹์„ ํ™œ์šฉํ•ด ๋นˆ๋„ํ‘œ์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ฐ€์žฅ ํ”ํ•œ ๋‹จ์–ด 10๊ฐœ๋ฅผ ๋ฝ‘์•„๋‚ด๋Š” ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์ด๋‹ค.

List<String> topTen = freq.keySet().stream()
    .sorted(comparing(freq::get).reversed())
    .limit(10)
    .collect(toList());

๋งต๊ณผ ์ŠคํŠธ๋ฆผ

ยท Collectors์˜ ๋‚˜๋จธ์ง€ 36๊ฐœ ๋ฉ”์„œ๋“œ ์ค‘ ๋Œ€๋ถ€๋ถ„์€ ์ŠคํŠธ๋ฆผ์„ ๋งต์œผ๋กœ ์ทจํ•ฉํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋‹ค.

- ์ด๋Š” ์ปฌ๋ ‰์…˜์— ์ทจํ•ฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ๋ณผ์žกํ•˜๋‹ค.

- ์ŠคํŠธ๋ฆผ์˜ ๊ฐ ์›์†Œ๋Š” ํ‚ค ํ•˜๋‚˜์™€ ๊ฐ’ ํ•˜๋‚˜์— ์—ฐ๊ด€๋˜์–ด ์žˆ๋‹ค. ๋‹ค์ˆ˜์˜ ์ŠคํŠธ๋ฆผ ์›์†Œ๊ฐ€ ๊ฐ™์€ ํ‚ค์— ์—ฐ๊ด€๋  ์ˆ˜๋„ ์žˆ๋‹ค.

ยท ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋งต ์ˆ˜์ง‘๊ธฐ: toMap(keyMap, valueMapper)

- ์ŠคํŠธ๋ฆผ ์›์†Œ๋ฅผ ํ‚ค์— ๋งคํ•‘ํ•˜๋Š” ํ•จ์ˆ˜์™€ ๊ฐ’์— ๋งคํ•‘ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค.

ํ•ด๋‹น ์ˆ˜์ง‘๊ธฐ๋Š” ์•„์ดํ…œ 34์—์„œ ์—ด๊ฑฐ ํƒ€์ž… ์ƒ์ˆ˜์˜ ๋ฌธ์ž์—ด ํ‘œํ˜„์„ ์—ด๊ฑฐ ํƒ€์ž… ์ž์ฒด์— ๋งคํ•‘ํ•˜๋Š” fromString์„ ๊ตฌํ˜„ํ•˜๋Š”๋ฐ ์‚ฌ์šฉํ–ˆ๋‹ค.

private static final Map<String, Operation> stringToEnum =
    Stream.of(values()).collect(
        toMap(Obejct::toString, e->e));

์ŠคํŠธ๋ฆผ์˜ ๊ฐ ์›์†Œ๊ฐ€ ๊ณ ์œ ํ•œ ํ‚ค์— ๋งคํ•‘๋˜์–ด ์žˆ์„ ๋•Œ ์ ํ•ฉํ•˜๋‹ค. ์ŠคํŠธ๋ฆผ ์›์†Œ ๋‹ค์ˆ˜๊ฐ€ ๊ฐ™์€ ํ‚ค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ํŒŒ์ดํ”„๋ผ์ธ์ด IllegalStateException์„ ๋˜์ง€๋ฉด ์ข…๋ฃŒ๋œ๋‹ค.

ยท ๋ณต์žกํ•œ ํ˜•ํƒœ์˜ toMap์ด๋‚˜ groupingBy๋Š” ์ด๋Ÿฐ ์ถฉ๋Œ์„ ๋‹ค๋ฃจ๋Š” ๋‹ค์–‘ํ•œ ์ „๋žต์„ ์ œ๊ณตํ•œ๋‹ค.

ex) toMap์— ํ‚ค ๋งคํผ์™€ ๊ฐ’ ๋งคํผ์™€ ํ•จ๊ป˜ ๋ณ‘ํ•ฉ(merge) ํ•จ์ˆ˜๊นŒ์ง€ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ณ‘ํ•ฉ ํ•จ์ˆ˜์˜ ํ˜•ํƒœ๋Š” BinaryOperator<U>์ด๋ฉฐ, ์—ฌ๊ธฐ์„œ U๋Š” ํ•ด๋‹น ๋งต์˜ ๊ฐ’ ํƒ€์ž…์ด๋‹ค. ๊ฐ™์€ ํ‚ค๋ฅผ ๊ณต์œ ํ•˜๋Š” ๊ฐ’๋“ค์€ ์ด ๋ณ‘ํ•ฉ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด ๊ธฐ์กด ๊ฐ’์— ํ•ฉ์ณ์ง„๋‹ค. ์˜ˆ์ปจ๋Œ€ ๋ณ‘ํ•ฉ ํ•จ์ˆ˜๊ฐ€ ๊ณฑ์…ˆ์ด๋ฉด, ํ‚ค๊ฐ€ ๊ฐ™์€ ๋ชจ๋“  ๊ฐ’(ํ‚ค/๊ฐ’ ๋งคํผ๊ฐ€ ์ •ํ•จ)์„ ๊ณฑํ•œ ๊ฒฐ๊ณผ๋ฅผ ์–ป๋Š”๋‹ค.

ยท ์ธ์ˆ˜ 3๊ฐœ๋ฅผ ๋ฐ›๋Š” toMap์€ ์–ด๋–ค ํ‚ค์™€ ๊ทธ ํ‚ค์— ์—ฐ๊ด€๋œ ์›์†Œ๋“ค ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ณจ๋ผ ์—ฐ๊ด€ ์ง“๋Š” ๋งต์„ ๋งŒ๋“ค ๋•Œ ์œ ์šฉํ•˜๋‹ค.

๋‹ค์Œ ์ฝ”๋“œ๋Š” ๋‹ค์–‘ํ•œ ์Œ์•…๊ฐ€์˜ ์•จ๋ฒ”๋“ค์„ ๋‹ด์€ ์ŠคํŠธ๋ฆผ์„ ๊ฐ€์ง€๊ณ , ์Œ์•…๊ฐ€์™€ ๊ทธ ์Œ์•…๊ฐ€์˜ ๋ฒ ์ŠคํŠธ ์•จ๋ฒ”์„ ์—ฐ๊ด€ ์ง“๋Š”๋‹ค.

// ๊ฐ ํ‚ค์™€ ํ•ด๋‹น ํ‚ค์˜ ํŠน์ • ์›์†Œ๋ฅผ ์—ฐ๊ด€ ์ง“๋Š” ๋งต์„ ์ƒ์„ฑํ•˜๋Š” ์ˆ˜์ง‘๊ธฐ
Map<Artist, Album> topHits = albums.collect(
    toMap(Album::artist, a->a, maxBy(comparing(Album::sales))));

๋น„๊ต์ž๋กœ BinaryOperator์—์„œ ์ •์  ์ž„ํฌํŠธํ•œ maxBy๋ผ๋Š” ์ •์  ํŒฉํ„ฐ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค. maxBy๋Š” Comparator<T>๋ฅผ ์ž…๋ ฅ๋ฐ›์•„ BinaryOperator<T>๋ฅผ ๋Œ๋ ค์ค€๋‹ค. ์ด ๊ฒฝ์šฐ ๋น„๊ต์ž ์ƒ์„ฑ ๋ฉ”์„œ๋“œ์ธ comparing์ด maxBy์— ๋„˜๊ฒจ์ค„ ๋น„๊ต์ž๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”๋ฐ, ์ž์‹ ์˜ ํ‚ค ์ถ”์ถœ ํ•จ์ˆ˜๋กœ Album:sales๋ฅผ ๋ฐ›์•˜๋‹ค.

ํ•ด๋‹น ์ฝ”๋“œ๋Š” ๋†€๋ž๊ฒŒ๋„ ์šฐ๋ฆฌ๊ฐ€ ํ’€๋ คํ•œ ๋ฌธ์ œ๋ฅผ ๊ทธ๋ž˜๋กœ ๊ธฐ์ˆ ํ•œ ์ฝ”๋“œ๊ฐ€ ๋˜์—ˆ๋‹ค. "์•จ๋ฒ” ์ŠคํŠธ๋ฆผ์„ ๋งต์œผ๋กœ ๋ฐ”๊พธ๋Š”๋ฐ, ์ด ๋งต์€ ๊ฐ ์Œ์•…๊ฐ€์™€ ๊ทธ ์Œ์•…๊ฐ€์˜ ๋ฒ ์ŠคํŠธ ์•จ๋ฒ”์„ ์ง์ง€์€ ๊ฒƒ์ด๋‹ค"

ยท ์ธ์ˆ˜๊ฐ€ 3๊ฐœ์ธ toMap์€ ์ถฉ๋Œ์ด ๋‚˜๋ฉด ๋งˆ์ง€๋ง‰ ๊ฐ’์„ ์ทจํ•˜๋Š” (last-write-wins) ์ˆ˜์ง‘๊ธฐ๋ฅผ ๋งŒ๋“ค ๋•Œ๋„ ์œ ์šฉํ•˜๋‹ค.

๋งŽ์€ ์ŠคํŠธ๋ฆผ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋น„๊ฒฐ์ •์ ์ด๋‹ค. ํ•˜์ง€๋งŒ ๋งคํ•‘ ํ•จ์ˆ˜๊ฐ€ ํ‚ค ํ•˜๋‚˜์— ์—ฐ๊ฒฐํ•ด์ค€ ๊ฐ’๋“ค์ด ๋ชจ๋‘ ๊ฐ™์„ ๋•Œ, ํ˜น์€ ๊ฐ’์ด ๋‹ค๋ฅด๋”๋ผ๋„ ๋ชจ๋‘ ํ—ˆ์šฉ๋˜๋Š” ๊ฐ’์ผ ๋•Œ ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•˜๋Š” ์ˆ˜์ง‘๊ธฐ๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

// ๋งˆ์ง€๋ง‰์— ์“ด ๊ฐ’์„ ์ทจํ•˜๋Š” ์ˆ˜์ง‘๊ธฐ
toMap(keyMapper, valueMapper, (oldVal, newVal) -> newVal)

ยท ์ธ์ˆ˜๊ฐ€ 4๊ฐœ์ธ toMap์€ ๋„ค ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋งต ํŒฉํ„ฐ๋ฆฌ๋ฅผ ๋ฐ›๋Š”๋‹ค.

- ์ด ์ธ์ˆ˜๋กœ EnumMap์ด๋‚˜ TreeMap์ฒ˜๋Ÿผ ์›ํ•˜๋Š” ํŠน์ • ๋งต ๊ตฌํ˜„์ฒด๋ฅด ์ง์ ‘ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ์œ„ ์„ธ ๊ฐ€์ง€ toMap์—๋Š” ๋ณ€์ข…์ด ์žˆ๋‹ค. ๊ทธ์ค‘ toConcurrentMap์€ ๋ณ‘๋ ฌ ์‹คํ–‰๋œ ํ›„ ๊ฒฐ๊ณผ๋กœ ConcurrentHashMap ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•œ๋‹ค.

groupingBy

ยท Collectors๊ฐ€ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ๋กœ ์ž…๋ ฅ์œผ๋กœ ๋ถ„๋ฅ˜ ํ•จ์ˆ˜(classifier)๋ฅผ ๋ฐ›๊ณ , ์ถœ๋ ฅ์œผ๋กœ๋Š” ์›์†Œ๋ฅผ ์นดํ…Œ๊ณ ๋ฆฌ๋ณ„๋กœ ๋ชจ์•„ ๋†“์€ ๋งต์„ ๋‹ด์€ ์ˆ˜์ง‘๊ธฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

- ๋ถ„๋ฅ˜ํ•จ์ˆ˜๋Š” ์ž…๋ ฅ๋ฐ›์€ ์›์†Œ๊ฐ€ ์†ํ•˜๋Š” ์นดํ…Œ๊ณ ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด ์นดํ…Œ๊ณ ๋ฆฌ๋Š” ํ•ด๋‹น ์›์†Œ์˜ ๋งต ํ‚ค๋กœ ์“ฐ์ธ๋‹ค.

ยท ์ฒซ ๋ฒˆ์งธ ๋ฒ„์ „: groupingBy ์ค‘ ํ˜•ํƒœ๊ฐ€ ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๊ฒƒ์€ ๋ถ„๋ฅ˜ ํ•จ์ˆ˜ ํ•˜๋‚˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ๋งต์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

- ๋ฐ˜ํ™˜๋œ ๋งต์— ๋‹ด๊ธด ๊ฐ๊ฐ์˜ ๊ฐ’์€ ํ•ด๋‹น ์นดํ…Œ๊ณ ๋ฆฌ์— ์†ํ•˜๋Š” ์›์†Œ๋ฅผ ๋‹ด์€ ๋ฆฌ์ŠคํŠธ๋‹ค.

์ด๋Š” ์•„์ดํ…œ45์˜ ์•„๋‚˜๊ทธ๋žจ ํ”„๋กœ๊ทธ๋žจ์— ์‚ฌ์šฉํ•œ ์ˆ˜์ง‘๊ธฐ๋กœ, ์•„ํŒŒ๋ฒณํ™”ํ•œ ๋‹จ์–ด๋ฅผ ์•ŒํŒŒ๋ฒณํ™” ๊ฒฐ๊ณผ๊ฐ€ ๊ฐ™์€ ๋‹จ์–ด๋“ค์˜ ๋ฆฌ์ŠคํŠธ๋กœ ๋งคํ•‘ํ•˜๋Š” ๋งต์„ ์ƒ์„ฑํ–ˆ๋‹ค.

words.collect(groupingBy(word -> alphabetize(word)))

ยท ๋‘ ๋ฒˆ์งธ ๋ฒ„์ „: ๋ถ„๋ฅ˜ํ•จ์ˆ˜์™€ ํ•จ๊ป˜ ๋‹ค์šด์ŠคํŠธ๋ฆผ ์ˆ˜์ง‘๊ธฐ๋ฅผ ๋ช…์‹œํ•˜๋ฉด, groupingBy๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ˆ˜์ง‘๊ธฐ๊ฐ€ ๋ฆฌ์ŠคํŠธ ์ด์™ธ์˜ ๊ฐ’์„ ๊ฐ–๋Š” ๋งต์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์ŠคํŠธ๋ฆผ ์ˆ˜์ง‘๊ธฐ์˜ ์—ญํ• : ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋ชจ๋“  ์›์†Œ๋ฅผ ๋‹ด์€ ์ŠคํŠธ๋ฆผ์œผ๋กœ๋ถ€ํ„ฐ ๊ฐ’์„ ์ƒ์„ฑํ•œ๋‹ค.

- ์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ toSet()์„ ๋„˜๊ธฐ๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๋Ÿฌ๋ฉด groupingBy๋Š” ์›์†Œ๋“ค์˜ ๋ฆฌ์ŠคํŠธ๊ฐ€ ์•„๋‹Œ ์ง‘ํ•ฉ(Set)์„ ๊ฐ’์œผ๋กœ ๊ฐ–๋Š” ๋งต์„ ๋งŒ๋“ ๋‹ค.

- toCollection(collectionFactory)๋ฅผ ๊ฑด๋„ค๋ฉด, ์ปฌ๋ ‰์…˜์„ ๊ฐ’์œผ๋กœ ๊ฐ–๋Š” ๋งต์„ ์ƒ์„ฑํ•œ๋‹ค.

- counting()์„ ๊ฑด๋„ค๋ฉด, ๊ฐ ์นดํ…Œ๊ณ ๋ฆฌ(ํ‚ค)๋ฅผ ํ•ด๋‹น ์นดํ…Œ๊ณ ๋ฆฌ์— ์†ํ•˜๋Š” ์›์†Œ์˜ ๊ฐœ์ˆ˜(๊น‚)์™€ ๋งคํ•‘ํ•œ ๋งต์„ ์–ป๋Š”๋‹ค.

Map<String, Long> freq = words.collect(groupingBy(String::toLowerCase, counting()));

ยท ์„ธ ๋ฒˆ์งธ ๋ฒ„์ „: ์•ž์„  ๋งค๊ฐœ๋ณ€์ˆ˜์— ์ถ”๊ฐ€๋กœ ๋งต ํŒฉํ„ฐ๋ฆฌ๋ฅผ ์ถ”๊ฐ€๋กœ ๋ฅผ ์ง€์ •ํ•˜๋ฉด, ๋งต๊ณผ ๊ทธ์•ˆ์— ๋‹ด๊ธด ์ปฌ๋ ‰์…˜์˜ ํƒ€์ž…์„ ๋ชจ๋‘ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์˜ˆ๋ฅผ ๋“ค์–ด TreeSet์ธ TreeMap์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ˆ˜์ง‘๊ธฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

- ์ด ๋ฉ”์„œ๋“œ๋Š” ์ ์ธต์  ์ธ์ˆ˜ ๋ชฉ๋ก ํŒจํ„ด(telescoping argument list pattern)์— ์–ด๊ธ‹๋‚œ๋‹ค. ์ฆ‰, mapFactory ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ downStream ๋งค๊ฐœ๋ณ€์ˆ˜๋ณด๋‹ค ์•ž์— ๋†“์ธ๋‹ค.

ยท ์œ„ ์„ธ ๊ฐ€์ง€ groupingBy ๊ฐ๊ฐ์— ๋Œ€์‘ํ•˜์—ฌ ๋ฉ”์„œ๋“œ์˜ ๋™์‹œ ์ˆ˜ํ–‰ ๋ฒ„์ „์ธ groupingByConcurrent ๋ฉ”์„œ๋“œ๋„ ์žˆ๋‹ค.

- ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” ConcurrentHashMap ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด์ค€๋‹ค.

ยท goupingBy์˜ ์‚ฌ์ดŒ๊ฒฉ์ธ partitionBy๋Š” ๋ถ„๋ฅ˜ ํ•จ์ˆ˜ ์ž๋ฆฌ์— ํ”„๋ ˆ๋””ํ‚คํŠธ(predicate)๋ฅผ ๋ฐ›๊ณ  ํ‚ค๊ฐ€ Boolean์ธ ๋งต์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

- ํ”„๋ ˆ๋””ํ‚คํŠธ์— ๋”ํ•ด ๋‹ค์šด์ŠคํŠธ๋ฆผ ์ˆ˜์ง‘๊ธฐ๊นŒ์ง€ ์ž…๋ ฅ๋ฐ›๋Š” ๋ฒ„์ „๋„ ๋‹ค์ค‘์ •์˜๋˜์–ด ์žˆ๋‹ค.

- ๋งŽ์ด ์“ฐ์ด์ง€๋Š” ์•Š๋Š”๋‹ค.

๊ทธ์™ธ ๋ฉ”์„œ๋“œ

ยท counting ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ˆ˜์ง‘๊ธฐ๋Š” ๋‹ค์šด์ŠคํŠธ๋ฆผ ์ˆ˜์ง‘๊ธฐ ์ „์šฉ์ด๋‹ค.

- Stream์˜ count ๋ฉ”์„œ๋“œ๊ฐ€ ์ง์ ‘ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์œผ๋‹ˆ collect(counting()) ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•  ์ผ์€ ์ „ํ˜€ ์—†๋‹ค.

- Collections์—๋Š” ์ด๋Ÿฐ ์†์„ฑ์˜ ๋ฉ”์„œ๋“œ๊ฐ€ 16๊ฐœ ๋” ์žˆ๋‹ค. ๊ทธ์ค‘ 9๊ฐœ๋Š” ์ด๋ฆ„์ด summing, averaging, summarizing์œผ๋กœ ์‹œ์ž‘ํ•˜๋ฉฐ, ๊ฐ๊ฐ int, long, double ์ŠคํŠธ๋ฆผ์šฉ์œผ๋กœ ํ•˜๋‚˜์”ฉ ์กด์žฌํ•œ๋‹ค.

ยท ๋‹ค์ค‘์ •์˜๋œ reducing ๋ฉ”์„œ๋“œ๋“ค, filteing, mapping, flatMapping, collectingAndThen ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋Š”๋ฐ, ๋Œ€๋ถ€๋ถ„ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” ์กด์žฌ๋ฅผ ๋ชจ๋ฅด๊ณ  ์žˆ์–ด๋„ ์ƒ๊ด€์—†๋‹ค.

- ์„ค๊ณ„ ๊ด€์ ์—์„œ ๋ณด๋ฉด, ์ด ์ˆ˜์ง‘๊ธฐ๋“ค์€ ์ŠคํŠธ๋ฆผ ๊ธฐ๋Šฅ์˜ ์ผ๋ถ€๋ฅผ ๋ณต์ œํ•˜์—ฌ ๋‹ค์šด์ŠคํŠธ๋ฆผ ์ˆ˜์ง‘๊ธฐ๋ฅผ ์ž‘์€ ์ŠคํŠธ๋ฆผ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜๊ฒŒ ํ•œ ๊ฒƒ์ด๋‹ค.

ยท Collectors์—๋Š” ์ด์™ธ์—๋„ 3๊ฐœ์˜ ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ, ์ˆ˜์ง‘๊ณผ๋Š” ๊ด€๋ จ์ด ์—†๋‹ค.

ยท minBy, maxBy๋Š” ์ธ์ˆ˜๋กœ ๋ฐ›์€ ๋น„๊ต์ž๋ฅผ ์ด์šฉํ•ด ์ŠคํŠธ๋ฆผ์—์„œ ๊ฐ’์ด ๊ฐ€์žฅ ์ž‘์€ ํ˜น์€ ๊ฐ€์žฅ ํฐ ์›์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

- Stream ์ธํ„ฐํŽ˜์ด์Šค์˜ min๊ณผ max ๋ฉ”์„œ๋“œ๋ฅผ ์‚ด์ง ์ผ๋ฐ˜ํ™”ํ•œ ๊ฒƒ์ด๋‹ค.

- java.util.function.BinaryOperator์˜ minBy์™€ maxBy ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ด์ง„ ์—ฐ์‚ฐ์˜ ์ˆ˜์ง‘๊ธฐ ๋ฒ„์ „์ด๋‹ค.

- joining์€ CharSequence ์ธ์Šคํ„ด์Šค์˜ ์ŠคํŠธ๋ฆผ์—๋งŒ ์ ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

- ๋งค๊ฐœ๋ณ€์ˆ˜๊ฐ€ ์—†๋Š” joining์€ ๋‹จ์ˆœํžˆ ์›์†Œ๋“ค์„ ์—ฐ๊ฒฐํ•˜๋Š” ์ˆ˜์ง‘๊ธฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

- ์ธ์ˆ˜๊ฐ€ 1๊ฐœ์ธ joining์€ CharSequence ํƒ€์ž…์˜ ๊ตฌ๋ถ„๋ฌธ์ž๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์—ฐ๊ฒฐ ๋ถ€์œ„์— ์ด ๊ตฌ๋ถ„๋ฌธ์ž๋ฅผ ์‚ฝ์ž…ํ•œ๋‹ค.

ex) ๊ตฌ๋ถ„๋ฌธ์ž๋กœ ์‰ผํ‘œ(,)๋ฅผ ์ž…๋ ฅํ•˜๋ฉด CSV ํ˜•ํƒœ์˜ ๋ฌธ์ž์—ด ์ƒ์„ฑํ•œ๋‹ค. ๋‹จ, ์ŠคํŠธ๋ฆผ์— ์‰ฝํ‘œ๋ฅผ ์ด๋ฏธ ํฌํ•จํ•œ ์›์†Œ๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ตฌ๋ถ„๋ฌธ์ž์™€ ๊ตฌ๋ณ„๋˜์ง€ ์•Š์œผ๋‹ˆ ์œ ๋…ํ•˜์ž.

- ์ธ์ˆ˜๊ฐ€ 3๊ฐœ์ธ joining์€ ๊ตฌ๋ถ„๋ฌธ์ž์— ๋”ํ•ด ์ ‘๋‘๋ฌธ์ž(prefix)์™€ ์ ‘๋ฏธ๋ฌธ์ž(suffix)๋„ ๋ฐ›๋Š”๋‹ค.

ex) ์ ‘๋‘, ๊ตฌ๋ถ„, ์ ‘๋ฏธ๋ฌธ์ž๋ฅผ '[', ',', ']'๋กœ ์ง€์ •ํ•˜์—ฌ ์–ป์€ ์ˆ˜์ง‘๊ธฐ๋Š” [came, saw, conquered]๊ฐ™์€ ๋ฌธ์ž์—ด์„ ์ƒ์„ฑํ•œ๋‹ค.

์•„์ดํ…œ 47. ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ๋Š” ์ŠคํŠธ๋ฆผ๋ณด๋‹ค ์ปฌ๋ ‰์…˜์ด ๋‚ซ๋‹ค


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ์›์†Œ ์‹œํ€ธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š”, ์ด๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ๋ฅผ ์›ํ•˜๋Š” ์‚ฌ์šฉ์ž์™€ ๋ฐ˜๋ณต์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธธ ์›ํ•˜๋Š” ์‚ฌ์šฉ์ž๊ฐ€ ๋ชจ๋‘ ์žˆ์Œ์„ ๋– ์˜ฌ๋ฆฌ๊ณ , ์–‘์ชฝ์„ ๋‹ค ๋งŒ์กฑ์‹œํ‚ค๋ ค ๋…ธ๋ ฅํ•˜์ž.

ยท ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ๊ทธ๋ ‡๊ฒŒ ํ•˜์ž.

ยท ๋ฐ˜ํ™˜ ์ „๋ถ€ํ„ฐ ์ด๋ฏธ ์›์†Œ๋“ค์„ ์ปฌ๋ ‰์…˜์— ๋‹ด์•„ ๊ด€๋ฆฌํ•˜๊ณ  ์žˆ๊ฑฐ๋‚˜ ์ปฌ๋ ‰์…˜์„ ํ•˜๋‚˜ ๋” ๋งŒ๋“ค์–ด๋„ ๋  ์ •๋„๋กœ ์›์†Œ ๊ฐœ์ˆ˜๊ฐ€ ์ ๋‹ค๋ฉด ArrayList ๊ฐ™์€ ํ‘œ์ค€ ์ปฌ๋ ‰์…˜์— ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•˜์ž. ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ์ „์šฉ ์ปฌ๋ ‰์…˜์„ ๊ตฌํ˜„ํ• ์ง€ ๊ณ ๋ฏผํ•˜์ž.

ยท ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒŒ ๋ถˆ๊ฐ€๋Šฅํ•˜๋ฉด ์ŠคํŠธ๋ฆผ๊ณผ Iterable ์ค‘ ๋” ์ž์—ฐ์Šค๋Ÿฌ์šด ๊ฒƒ์„ ๋ฐ˜ํ™˜ํ•˜๋ผ.

- ๋งŒ์•ฝ ๋‚˜์ค‘์— Stream ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ Iterable์„ ์ง€์›ํ•˜๋„๋ก ์ž๋ฐ”๊ฐ€ ์ˆ˜์ •๋œ๋‹ค๋ฉด, ๊ทธ๋•Œ๋Š” ์•ˆ์‹ฌํ•˜๊ณ  ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด ๋  ๊ฒƒ์ด๋‹ค(์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ์™€ ๋ฐ˜๋ณต ๋ชจ๋‘์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ).

์ž๋ฐ”8 ์ด์ „์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…

ยท ์ผ๋ จ์˜ ์›์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋Š” ์ˆ˜์—…์ด ๋งŽ์œผ๋ฉฐ, ์ž๋ฐ” 7๊นŒ์ง€๋Š” ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ Collection, Set, List ๊ฐ™์€ ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค ๋˜๋Š” Iterable์ด๋‚˜ ๋ฐฐ์—ด์„ ์ผ๋‹ค.

- ๊ธฐ๋ณธ์€ ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค์˜€๊ณ  for-each ๋ฌธ์—์„œ๋งŒ ์“ฐ์ด๊ฑฐ๋‚˜, ๋ฐ˜ํ™˜๋œ ์›์†Œ ์‹œํ€ธ์Šค๊ฐ€ contains(Obejct) ๊ฐ™์€ ์ผ๋ถ€ Collection ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†์„ ๋•Œ๋Š” Iterable ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ผ๋‹ค.

- ๋ฐ˜ํ™˜ ์›์†Œ๋“ค์ด ๊ธฐ๋ณธ ํƒ€์ž…์ด๊ฑฐ๋‚˜ ์„ฑ๋Šฅ์— ๋ฏผ๊ฐํ•œ ์ƒํ™ฉ์ด๋ผ๋ฉด ๋ฐฐ์—ด์„ ์ผ๋‹ค.

์ž๋ฐ”8 ์ดํ›„์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…

ยท ์ž๋ฐ”8์—์„œ ์ŠคํŠธ๋ฆผ์ด ๋“ฑ์žฅํ•˜๋ฉด์„œ ๋ฐ˜ํ™˜ ํƒ€์ž…์˜ ์„ ํƒ์ด ๋ณต์žกํ•œ ์ผ์ด ๋˜์—ˆ๋‹ค.

Steam๊ณผ Iterable

ยท ์›์†Œ ์‹œํ€ธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ๋Š” ๋‹น์—ฐํžˆ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค. ํ•˜์ง€๋งŒ, ์ŠคํŠธ๋ฆผ์€ ๋ฐ˜๋ณต(iteration)์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ๋‹ค.

- Stream ์ธํ„ฐํŽ˜์ด์Šค๋Š” Iterable ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ •์˜ํ•œ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์ „๋ถ€ ํฌํ•จํ•˜๋ฉฐ, Iterable ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ •์˜ํ•œ ๋ฐฉ์‹๋Œ€๋กœ ๋™์ž‘ํ•œ๋‹ค. ํ•˜์ง€๋งŒ Stream์ด Iterable์„ ํ™•์žฅ(extend)ํ•˜์ง€ ์•Š์•„์„œ for-each๋กœ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์—†๋‹ค.

- ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•ด์ค„ ๋ฉ‹์ง„ ์šฐํšŒ๋กœ๋Š” ์—†๋‹ค.

Stream์˜ iterator ๋ฉ”์„œ๋“œ์— ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ๊ฑด๋„ค๋ฉด ๋ฌธ์ œ๊ฐ€ ํ•ด๊ฒฐ๋  ๊ฒƒ ๊ฐ™์ง€๋งŒ, ๋‹ค์Œ ์ฝ”๋“œ๋Š” ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๋ฅผ ๋‚ธ๋‹ค.

// ์ž๋ฐ” ํƒ€์ž… ์ถ”๋ก ์˜ ํ•œ๊ณ„๋กœ ์ปดํŒŒ์ผ๋˜์ง€ ์•Š๋Š”๋‹ค.
for (ProcessHandle ph : ProcessHandle.allProcesses()::iterator) {
    // ํ”„๋กœ์„ธ์Šค๋ฅผ ์‹œ์ž‘ํ•œ๋‹ค.
}

์ด ์˜ค๋ฅ˜๋ฅผ ๊ณ ์น˜๋ ค๋ฉด, ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ๋งค๊ฐœ๋ณ€์ˆ˜ํ™”๋œ Iterable๋กœ ์ ์ ˆํžˆ ํ˜•๋ณ€ํ™˜ํ•ด์•ผ ํ•œ๋‹ค. ์ž‘๋™์€ ํ•˜์ง€๋งŒ ์‹ค์ „์— ์“ฐ๊ธฐ์— ๋‚œ์žกํ•˜๊ณ , ์ง๊ด€์„ฑ์ด ๋–จ์–ด์ง„๋‹ค.

// ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜๋ณตํ•˜๊ธฐ ์œ„ํ•œ '๋”์ฐํ•œ' ์šฐํšŒ ๋ฐฉ๋ฒ•
for(ProcessHandle ph : (Iterable<ProcessHandle>) ProcessHandle.allProcesses().iterator()) {
    // ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.
}

์–ด๋Œ‘ํ„ฐ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ƒํ™ฉ์ด ๋‚˜์•„์ง„๋‹ค. ์ž๋ฐ”๋Š” ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

- ์ž๋ฐ”์˜ ํƒ€์ž… ์ถ”๋ก ์ด ๋ฌธ๋งฅ์„ ์ž˜ ํŒŒ์•…ํ•˜์—ฌ ์–ด๋Œ‘ํ„ฐ ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ๋”ฐ๋กœ ํ˜•๋ณ€ํ™˜ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.

// Stream<E>์„ Iterable<E>๋กœ ์ค‘๊ฐœํ•ด์ฃผ๋Š” ์–ด๋Œ‘ํ„ฐ
public static<E> Iterable<E> iterableOf(Stream<E> stream) {
    return steam::iterator;
}

์–ด๋Œ‘ํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์–ด๋–ค ์ŠคํŠธ๋ฆผ๋„ for-each ๋ฌธ์œผ๋กœ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท Iterable์—์„œ Steam์˜ ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ๋„ ์žˆ๋‹ค.

- ์•„์ดํ…œ 45์˜ ์•„๋‚˜๊ทธ๋žจ ํ”„๋กœ๊ทธ๋žจ์—์„œ ์ŠคํŠธ๋ฆผ ๋ฒ„์ „์€ ์‚ฌ์ „์„ ์ฝ์„ ๋•Œ Files.lines ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ–ˆ๊ณ , ๋ฐ˜๋ณต ๋ฒ„์ „์€ ์Šค์บ๋„ˆ๋ฅผ ์ด์šฉํ–ˆ๋‹ค.

- ๋‘˜ ์ค‘ ํŒŒ์ผ์„ ์ฝ๋Š” ๋™์•ˆ ๋ฐœ์ƒํ•˜๋Š” ๋ชจ๋“  ์˜ˆ์™ธ๋ฅผ ์•Œ์•„์„œ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค๋Š” ์ ์—์„œ Files.lines ์ชฝ์ด ๋” ์šฐ์ˆ˜ํ•˜๋‹ค.

- ์ด์ƒ์ ์œผ๋กœ๋Š” ๋ฐ˜๋ณต ๋ฒ„์ „์—์„œ๋„ Files.lines๋ฅผ ์จ์•ผ ํ–ˆ๋‹ค.

API๊ฐ€ Iterable๋งŒ ๋ฐ˜ํ™˜ํ•˜๋ฉด, ์ด๋ฅผ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ์–ด๋Œ‘ํ„ฐ๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์ž๋ฐ”๋Š” ์ด๋ฅผ ์œ„ํ•œ ์–ด๋Œ‘ํ„ฐ๋„ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค.

// Iterable<E>๋ฅผ Stream<E>๋กœ ์ค‘๊ฐœํ•ด์ฃผ๋Š” ์–ด๋Œ‘ํ„ฐ
public static<E> Stream<E> streamOf(Iterable<E> iterable) {
    return StreamSupport.stream(iterable.spliterator(), false);
}

ยท ๊ฐ์ฒด ์‹œํ€ธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š”๋ฐ, ์ด ๋ฉ”์„œ๋“œ๊ฐ€ ์˜ค์ง ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ๋งŒ ์“ฐ์ผ ๊ฑธ ์•ˆ๋‹ค๋ฉด ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜์ž.

ยท ๋ฐ˜ํ™˜๋œ ๊ฐ์ฒด๋“ค์ด ๋ฐ˜๋ณต๋ฌธ์—์„œ๋งŒ ์“ฐ์ผ ๊ฑธ ์•ˆ๋‹ค๋ฉด Iterable์„ ๋ฐ˜ํ™˜ํ•˜์ž.

ยท ๊ณต๊ฐœ API๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‚ฌ์šฉํ•˜๋Š” ์‚ฌ๋žŒ๊ณผ ๋ฐ˜๋ณต๋ฌธ์—์„œ ์“ฐ๋ ค๋Š” ์‚ฌ๋žŒ ๋ชจ๋‘๋ฅผ ๋ฐฐ๋ คํ•ด์•ผ ํ•œ๋‹ค.

- ์‚ฌ์šฉ์ž ๋Œ€๋ถ€๋ถ„์ด ํ•œ ๋ฐฉ์‹๋งŒ ์‚ฌ์šฉํ•  ๊ฑฐ๋ผ๋Š” ๊ทผ๊ฑฐ๊ฐ€ ์—†๋‹ค๋ฉด ๋ง์ด๋‹ค.

Collection ์ธํ„ฐํŽ˜์ด์Šค

ยท ์›์†Œ ์‹œํ€ธ์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ณต๊ฐœ API์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์—๋Š” Collection์ด๋‚˜ ๊ทธ ํ•˜์œ„ ํƒ€์ž…์„ ์“ฐ๋Š” ๊ฒŒ ์ผ๋ฐ˜์ ์œผ๋กœ ์ตœ์„ ์ด๋‹ค.

- Collection ์ธํ„ฐํŽ˜์ด์Šค๋Š” Iterable์˜ ํ•˜์œ„ ํƒ€์ž…์ด๊ณ , stream ๋ฉ”์„œ๋“œ๋„ ์ œ๊ณตํ•˜๋‹ˆ ๋ฐ˜๋ณต๊ณผ ์ŠคํŠธ๋ฆผ์„ ๋™์‹œ์— ์ง€์›ํ•˜๊ธฐ ๋–„๋ฌธ์ด๋‹ค.

ยท Arrays ์—ญ์‹œ Arrays.asList์™€ Stream.of ๋ฉ”์„œ๋“œ๋กœ ์†์‰ฝ๊ฒŒ ๋ฐ˜๋ณต๊ณผ ์ŠคํŠธ๋ฆผ์„ ์ง€์›ํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท ๋ฐ˜ํ™˜ํ•˜๋Š” ์‹œํ€ธ์Šค์˜ ํฌ๊ธฐ๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ ค๋„ ์•ˆ์ „ํ•  ๋งŒํผ ์ž‘๋‹ค๋ฉด ArrayList๋‚˜ HashSet ๊ฐ™์€ ํ‘œ์ค€ ์ปฌ๋ ‰์…˜ ๊ตฌํ˜„์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒŒ ์ตœ์„ ์ผ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋‹จ์ง€ ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ์ด์œ ๋กœ ๋ฉ์น˜ ํฐ ์‹œํ€ธ์Šค๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ ค์„œ๋Š” ์•ˆ ๋œ๋‹ค.

์ „์šฉ ์ปฌ๋ ‰์…˜

ยท ๋ฐ˜ํ™˜ํ•  ์‹œํ€ธ์Šค๊ฐ€ ํฌ์ง€๋งŒ ํ‘œํ˜„์„ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ „์šฉ ์ปฌ๋ ‰์…˜์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ์•ˆ์„ ๊ฒ€ํ† ํ•˜์ž.

์ฃผ์–ด์ง„ ์ง‘ํ•ฉ์˜ ๋ฉฑ์ง‘ํ•ฉ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ƒํ™ฉ์„ ์ƒ๊ฐํ•˜์ž.

- ๋ฉฑ์ง‘ํ•ฉ: ํ•œ ์ง‘ํ•ฉ์˜ ๋ชจ๋“  ๋ถ€๋ถ„์ง‘ํ•ฉ์„ ์›์†Œ๋กœ ํ•˜๋Š” ์ง‘ํ•ฉ

{a, b, c}์˜ ๋ฉฑ์ง‘ํ•ฉ์€ {{}, {a}, {b}, {c}, {a, b}, {a, c}, {b, c}, {a, b, c}}๋‹ค. ์›์†Œ ๊ฐœ์ˆ˜๊ฐ€ n๊ฐœ๋ฉด ๋ฉฑ์ง‘ํ•ฉ์˜ ์›์†Œ ๊ฐœ์ˆ˜๋Š” 2^n์ด ๋œ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฉฑ์ง‘ํ•ฉ์„ ํ‘œ์ค€ ์ปฌ๋ ‰์…˜ ๊ตฌํ˜„์ฒด์— ์ €์žฅํ•˜๋ ค๋Š” ์ƒ๊ฐ์€ ์œ„ํ—˜ํ•˜๋‹ค. ํ•˜์ง€๋งŒ, AbstractList๋ฅผ ์ด์šฉํ•˜๋ฉด ํ›Œ๋ฅญํ•œ ์ „์šฉ ์ปฌ๋ ‰์…˜์„ ์†์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋น„๊ฒฐ์€ ๋ฉฑ์ง‘ํ•ฉ์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฐ ์›์†Œ์˜ ์ธ๋ฑ์Šค๋ฅผ ๋น„ํŠธ ๋ฒกํ„ฐ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์ธ๋ฑ์Šค์˜ n๋ฒˆ์งธ ๋น„ํŠธ ๊ฐ’์€ ๋ฉฑ์ง‘ํ•ฉ์˜ ํ•ด๋‹น ์›์†Œ๊ฐ€ ์›๋ž˜ ์ง‘ํ•ฉ์˜ n๋ฒˆ์งธ ์›์†Œ๋ฅผ ํฌํ•จํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ๋ ค์ค€๋‹ค. ๋”ฐ๋ผ์„œ 0๋ถ€ํ„ฐ 2^n - 1๊นŒ์ง€์˜ ์ด์ง„์ˆ˜์™€ ์›์†Œ n๊ฐœ์ธ ์ง‘ํ•ฉ์˜ ๋ฉฑ์ง‘ํ•ฉ๊ณผ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋งคํ•‘๋œ๋‹ค.

// ์ž…๋ ฅ ์ง‘ํ•ฉ์˜ ๋ฉฑ์ง‘ํ•ฉ์„ ์ „์šฉ ์ปจ๋ ‰์…˜์— ๋‹ด์•„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
public class PowerSet {
    public static final <E> Collection<Set<E>> of(Set<E> s) {
        List<E> src = new ArrayList<>(s);
            if(src.size() > 30) {
                throw new IllegalArgumentException("์ง‘ํ•ฉ์— ์›์†Œ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์Šต๋‹ˆ๋‹ค(์ตœ๋Œ€ 30๊ฐœ).: " + s);
            }
            
            return new AbstractList<Set<E>>() {
                @Override
                public int size() {
                    return 1 << src.size();
                }
                
                @Override
                public boolean contains(Object o) {
                    return o instanceof Set && src.containsAll((Set) o);
                }
                
                @Override
                public Set<E> get(int index) {
                    Set<E> result = new HashSet<>();
                        for (int i = 0; index != 0; i++, index >>=1) {
                            if((index & 1) == 1) {
                                result.add(src.get(i));
                            }
                        }
                        return result;
                        }
                        };
                        }
                        }

ยท AbstractCollection์„ ํ™œ์šฉํ•ด์„œ Collection ๊ตฌํ˜„์ฒด๋ฅผ ์ž‘์„ฑํ•  ๋•Œ๋Š” Iterable์šฉ ๋ฉ”์„œ๋“œ ์™ธ์— contains์™€ size๋งŒ ๋” ๊ตฌํ˜„ํ•˜๋ฉด ๋œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋“ค์€ ์†์‰ฝ๊ฒŒ ํšจ์œจ์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

ยท (๋ฐ˜๋ณต์ด ์‹œ์ž‘๋˜๊ธฐ ์ „์—๋Š” ์‹œํ€ธ์Šค์˜ ๋‚ด์šฉ์„ ํ™•์ •ํ•  ์ˆ˜ ์—†๋Š” ๋“ฑ์˜ ์‚ฌ์œ ๋กœ) contains์™€ size๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒŒ ๋ถˆ๊ฐ€๋Šฅํ•  ๋•Œ๋Š” ์ปฌ๋Ÿญ์„ผ๋ณด๋‹ค ์ŠคํŠธ๋ฆผ์ด๋‚˜ Iterable์„ (๋˜๋Š” ๋‘˜ ๋‹ค๋ฅผ) ๋ฐ˜ํ™˜ํ•˜๋Š” ํŽธ์ด ๋‚ซ๋‹ค.

ยท Collection์„ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์“ธ ๋•Œ์˜ ๋‹จ์ :

- ์œ„ ์ฝ”๋“œ์—์„œ ์ž…๋ ฅ ์ง‘ํ•ฉ์˜ ์›์†Œ ์ˆ˜๊ฐ€ 30์„ ๋„˜์œผ๋ฉด PowerSet.of๊ฐ€ ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค. ์ด๋Š” Stream์ด๋‚˜ Iterable์ด ์•„๋‹Œ Collection์„ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์“ธ ๋•Œ์˜ ๋‹จ์ ์„ ์ž˜ ๋ณด์—ฌ์ค€๋‹ค.

- Collection์˜ size ๋ฉ”์„œ๋“œ๊ฐ€ int ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ PowerSet.of๊ฐ€ ๋ฐ˜ํ™˜๋˜๋Š” ์‹œํ€ธ์Šค์˜ ์ตœ๋Œ€ ๊ธธ์ด๋Š” Integer.MAX_VALUE ํ˜น์€ 2^32 -1๋กœ ์ œํ•œ๋œ๋‹ค.

- Collection ๋ช…์„ธ์— ๋”ฐ๋ฅด๋ฉด ์ปฌ๋ ‰์…˜์ด ๋” ํฌ๊ฑฐ๋‚˜ ์‹ฌ์ง€์–ด ๋ฌดํ•œ์ผ ๋•Œ size๊ฐ€ 2^31 -1์„ ๋ฐ˜ํ™˜ํ•ด๋„ ๋˜์ง€๋งŒ ๋งŒ์กฑ์Šค๋Ÿฌ์šด ํ•ด๋ฒ•์€ ์•„๋‹ˆ๋‹ค.

ยท ๋•Œ๋กœ๋Š” ๋‹จ์ˆœํžˆ ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฌ์šด ์ชฝ์„ ์„ ํƒํ•˜๊ธฐ๋„ ํ•œ๋‹ค.

์ž…๋ ฅ ๋ฆฌ์ŠคํŠธ์˜ ์—ฐ์†์ ์ธ ๋ถ€๋ถ„๋ฆฌ์ŠคํŠธ๋ฅผ ๋ชจ๋‘ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ž‘์„ฑํ•œ๋‹ค๊ณ  ํ•˜์ž. ํ•„์š”ํ•œ ๋ถ€๋ถ„๋ฆฌ์ŠคํŠธ๋ฅผ ๋งŒ๋“ค์–ด ํ‘œ์ค€ ์ปฌ๋ ‰์…˜์— ๋‹ด๋Š” ์ฝ”๋“œ๋Š” 3์ค„์ด๋ฉด ๋˜์ง€๋งŒ, ์ด ์ปฌ๋ ‰์…˜์€ ์ž…๋ ฅ ๋ฆฌ์ŠคํŠธ ํฌ๊ธฐ์˜ ๊ฑฐ๋“ญ์ œ๊ณฑ๋งŒํผ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ์ฐจ์ง€ํ•œ๋‹ค. ๋ฉฑ์ง‘ํ•ฉ ๋•Œ์ฒ˜๋Ÿผ ์ „์šฉ ์ปฌ๋ ‰์…˜์„ ๊ตฌํ˜„ํ•˜๊ธฐ๋ž€ ์ง€๋ฃจํ•œ ์ผ์ด๋‹ค. ํŠนํžˆ ์ž๋ฐ”๋Š” ์ด๋Ÿด ๋•Œ ์“ธ๋งŒํ•œ ๊ณจ๊ฒฉ Iterator๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š”๋‹ค.

ํ•˜์ง€๋งŒ ์ž…๋ ฅ ๋ฆฌ์ŠคํŠธ์˜ ๋ชจ๋“  ๋ถ€๋ถ„๋ฆฌ์ŠคํŠธ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ธฐ๋Š” ์–ด๋ ต์ง€ ์•Š๋‹ค. ์ฒซ ๋ฒˆ์งธ ์›์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ๋ถ€๋ถ„๋ฆฌ์ŠคํŠธ๋ฅผ ๊ทธ ๋ฆฌ์ŠคํŠธ์˜ ํ”„๋ฆฌํ”ฝ์Šค๋ผ ํ•ด๋ณด์ž (์˜ˆ: {a,b,c}์˜ ํ”„๋ฆฌํ•„์Šค๋Š” {a}, {a, b}, {a,b,c}). ๊ฐ™์€ ์‹์œผ๋กœ ๋งˆ์ง€๋ง‰ ์›์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ๋ถ€๋ถ„๋ฆฌ์ŠคํŠธ๋ฅผ ๊ทธ ๋ฆฌ์ŠคํŠธ์˜ ์„œํ”ฝ์Šค๋ผ๊ณ  ํ•˜์ž(์˜ˆ: {a,b,c}์˜ ์„œํ”ฝ์Šค๋Š” {a,b,c}, {b,c}, {c}). ์ด์ œ ์–ด๋–ค ๋ฆฌ์ŠคํŠธ์˜ ๋ถ€๋ถ„๋ฆฌ์ŠคํŠธ๋Š” ๋‹จ์ˆœํžˆ ๊ทธ ๋ฆฌ์ŠคํŠธ์˜ ํ”„๋ฆฌํ”ฝ์Šค์˜ ์„œํ•„์Šค์— ๋นˆ ๋ฆฌ์ŠคํŠธ ํ•˜๋‚˜๋งŒ ์ถ”๊ฐ€ํ•˜๋ฉด ๋œ๋‹ค.

public class SubList {
    
    public static <E> Stream<List<E>> of(List<E> list) {
        return Stream.concat(Stream.of(Collections.emptyList()),
            prefixes(list).flatMap(SubList::suffixes));
    }
    
    public static <E> Stream<List<E>> prefixes(List<E> list) {
        return IntStream.rangeClosed(1, list.size())
            .mapToObj(end -> list.subList(0, end));
    }
    
    public static <E> Stream<List<E>> suffixes(List<E> list) {
        return IntStream.rangeClosed(0, list.size())
            .mapToObj(start -> list.subList(start, list.size()));
    }
    }

Stream.concat ๋ฉ”์„œ๋“œ๋Š” ๋ฐ˜ํ™˜๋˜๋Š” ์ŠคํŠธ๋ฆผ์— ๋นˆ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉฐ, flatMap ๋ฉ”๋”๋“œ(์•„์ดํ…œ 45)๋Š” ๋ชจ๋“  ํ”„๋ฆฌํ”ฝ์Šค์˜ ๋ชจ๋“  ์„œํ”ฝ์Šค๋กœ ๊ตฌ์„ฑ๋œ ํ•˜๋‚˜์˜ ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ ๋‹ค. ๋งˆ์ง€๋ง‰์œผ๋กœ ํ”„๋ฆฌํ”ฝ์Šค๋“ค๊ณผ ์„œํ”ฝ์Šค๋“ค์˜ ์ŠคํŠธ๋ฆผ์€ IntStream.range์™€ IntStream.rangeClose๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ฐ์†๋œ ์ •์ˆ˜๊ฐ’๋“ค์„ ๋งคํ•‘ํ•ด ๋งŒ๋“ ๋‹ค.

// ์ž…๋ ฅ ๋ฆฌ์ŠคํŠธ์˜ ๋ชจ๋“  ๋ถ€๋ถ„๋ฆฌ์ŠคํŠธ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
public static <E> Stream<List<E>> of(List<E> list) {
    return IntStream.range(0, list.size())
        .mapToObj(start ->
            IntStream.rangeClosed(start + 1, list.size())
                .mapToObj(end -> list.subList(start, end)))
                .flatMap(x -> x);
            }

์•„์ดํ…œ 48. ์ŠคํŠธ๋ฆผ ๋ณ‘๋ ฌํ™”๋Š” ์ฃผ์˜ํ•ด์„œ ์ ์šฉํ•˜๋ผ


ํ•ต์‹ฌ ์ •๋ฆฌ

ยท ๊ณ„์‚ฐ๋„ ์˜ฌ๋ฐ”๋กœ ์ˆ˜ํ–‰ํ•˜๊ณ  ์„ฑ๋Šฅ๋„ ๋นจ๋ผ์งˆ ๊ฑฐ๋ผ๋Š” ํ™•์‹  ์—†์ด๋Š” ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌํ™”๋Š” ์‹œ๋„์กฐ์ฐจ ํ•˜์ง€ ๋ง๋ผ

ยท ์ŠคํŠธ๋ฆผ์„ ์ž˜๋ชป ๋ณ‘๋ ฌํ™”ํ•˜๋ฉด ํ”„๋กœ๊ทธ๋žจ์„ ์˜ค๋™์ž‘ํ•˜๊ฒŒ ํ•˜๊ฑฐ๋‚˜ ์„ฑ๋Šฅ์„ ๊ธ‰๊ฒฉํžˆ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค.

ยท ๋ณ‘๋ ฌํ™”ํ•˜๋Š” ํŽธ์ด ๋‚ซ๋‹ค๊ณ  ๋ฏฟ๋”๋ผ๋„, ์ˆ˜์ • ํ›„์˜ ์ฝ”๋“œ๊ฐ€ ์—ฌ์ „ํžˆ ์ •ํ™•ํ•œ์ง€ ํ™•์ธํ•˜๊ณ  ์šด์˜ ํ™˜๊ฒฝ๊ณผ ์œ ์‚ฌํ•œ ์กฐ๊ฑด์—์„œ ์ˆ˜ํ–‰ํ•ด๋ณด๋ฉฐ ์„ฑ๋Šฅ์ง€ํ‘œ๋ฅผ ์œ ์‹ฌํžˆ ๊ด€์ฐฐ ํ•˜์ž. ๊ณ„์‚ฐ๋„ ์ •ํ™•ํ•˜๊ณ  ์„ฑ๋Šฅ๋„ ์ข‹์•„์กŒ์Œ์ด ํ™•์‹คํ•ด์กŒ์„ ๋•Œ๋งŒ ๋ณ‘๋ ฌํ™” ๋ฒ„์ „ ์ฝ”๋“œ๋ฅผ ์šด์˜ ์ฝ”๋“œ์— ๋ฐ˜์˜ํ•˜์ž.

์ž๋ฐ”์˜ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ

์ฃผ๋ฅ˜ ์–ธ์–ด ์ค‘, ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ธก๋ฉด์—์„œ ์ž๋ฐ”๋Š” ํ•ญ์ƒ ์•ž์„œ๊ฐ”๋‹ค.

ยท ์ฒ˜์Œ ๋ฆด๋ฆฌ์Šค๋œ 1996๋…„๋ถ€ํ„ฐ ์Šค๋ ˆ๋“œ, ๋™๊ธฐํ™”, wait/notify๋ฅผ ์ง€์›ํ–ˆ๋‹ค.

ยท ์ž๋ฐ” 5๋ถ€ํ„ฐ ๋™์‹œ์„ฑ ์ปฌ๋ ‰์…˜์€ java.util.concurrent ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์™€ ์‹คํ–‰์ž(Executor) ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ง€์›ํ–ˆ๋‹ค.

ยท ์ž๋ฐ” 7๋ถ€ํ„ฐ ๊ณ ์„ฑ๋Šฅ ๋ณ‘๋ ฌ ๋ถ„ํ•ด(parallel decom-position) ํ”„๋ ˆ์ž„์›Œํฌ์ธ ํฌํฌ-์กฐ์ธ(fork-join) ํŒจํ‚ค์ง€๋ฅผ ์ถ”๊ฐ€ํ–ˆ๋‹ค.

ยท ์ž๋ฐ” 8๋ถ€ํ„ฐ๋Š” parallel ๋ฉ”์„œ๋“œ๋งŒ ํ•œ ๋ฒˆ ํ˜ธ์ถœํ•˜๋ฉด ํŒŒ์ดํ”„๋ผ์ธ์„ ๋ณ‘๋ ฌ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ŠคํŠธ๋ฆผ์„ ์ง€์›ํ–ˆ๋‹ค.

ยท ์ž๋ฐ”๋กœ ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ž‘์„ฑํ•˜๊ธฐ๊ฐ€ ์ ์  ์‰ฌ์›Œ์ง€๊ณ  ์žˆ์ง€๋งŒ, ์ด๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ณ  ๋น ๋ฅด๊ฒŒ ์ž‘์„ฑํ•˜๋Š” ์ผ์€ ์—ฌ์ „ํžˆ ์–ด๋ ค์šด ์ž‘์—…์ด๋‹ค.

์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌํ™”์˜ ์ž˜๋ชป๋œ ์‚ฌ์šฉ

ยท ๋™์‹œ์„ฑ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ํ•  ๋•Œ๋Š” ์•ˆ์ „์„ฑ๊ณผ ์‘๋‹ต ๊ฐ€๋Šฅ ์ƒํƒœ๋ฅผ ์œ ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์• ์จ์•ผ ํ•˜๋Š”๋ฐ, ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ๋„ ๋‹ค๋ฅผ ๋ฐ” ์—†๋‹ค.

์•„์ดํ…œ 45์˜ ๋ฉ”๋ฅด์„ผ ์†Œ์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ์„ ๋‹ค์‹œ ์‚ดํŽด๋ณด์ž

public class Main {
    // ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•ด ์ฒ˜์Œ 20๊ฐœ์˜ ๋ฉ”๋ฅด์„ผ ์†Œ์ˆ˜๋ฅผ ์ƒ์„ฑํ•˜๋Š” ํ”„๋กœ๊ทธ๋žจ
    public static void main(String[] args) {
        long beforeTime = System.currentTimeMillis(); //์ฝ”๋“œ ์‹คํ–‰ ์ „์— ์‹œ๊ฐ„ ๋ฐ›์•„์˜ค๊ธฐ
        
        primes().map(prime -> TWO.pow(prime.intValue()).subtract(ONE))
            .filter(mersenne -> mersenne.isProbablePrime(50))
            .limit(20)
            .forEach(System.out::println);
        
        long afterTime = System.currentTimeMillis(); // ์ฝ”๋“œ ์‹คํ–‰ ํ›„์— ์‹œ๊ฐ„ ๋ฐ›์•„์˜ค๊ธฐ
        long secDiffTime = (afterTime - beforeTime)/1000; //๋‘ ์‹œ๊ฐ„์— ์ฐจ ๊ณ„์‚ฐ
        System.out.println("์‹œ๊ฐ„์ฐจ์ด(m) : "+secDiffTime);
    }
    
    static Stream<BigInteger> primes() {
        return Stream.iterate(TWO, BigInteger::nextProbablePrime);
    }
    }

๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋‹ˆ 7์ดˆ๊ฐ€ ๊ฑธ๋ ธ๋‹ค.

์†๋„๋ฅผ ๋†’์ด๊ธฐ ์œ„ํ•ด ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์˜ parallel()์„ ํ˜ธ์ถœํ•˜๊ฒ ๋‹ค๋Š” ์ˆœ์ง„ํ•œ ์ƒ๊ฐ์„ ํ–ˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž.

primes().map(prime -> TWO.pow(prime.intValue()).subtract(ONE))
    .parallel()
    .filter(mersenne -> mersenne.isProbablePrime(50))
    .limit(20)
    .forEach(System.out::println);

์˜ˆ์ƒ๊ณผ๋Š” ๋‹ค๋ฅด๊ฒŒ ์œ„ ์ฝ”๋“œ๋Š” ์•„๋ฌด๊ฒƒ๋„ ์ถœ๋ ฅํ•˜์ง€ ๋ชปํ•˜๋ฉด์„œ CPU๋Š” 90%๋‚˜ ์žก์•„๋จน๋Š” ์ƒํƒœ๊ฐ€ ๋ฌดํ•œํžˆ ๊ณ„์†๋œ๋‹ค(์‘๋‹ต ๋ถˆ๊ฐ€: liveness failure).

- ์›์ธ: ์ŠคํŠธ๋ฆผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์ด ํŒŒ์ดํ”„๋ผ์ธ์„ ๋ณ‘๋ ฌํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋‚ด์ง€ ๋ชปํ–ˆ์ง€ ๋•Œ๋ฌธ์ด๋‹ค.

ยท ํ™˜๊ฒฝ์ด ์•„๋ฌด๋ฆฌ ์ข‹๋”๋ผ๋„ ๋ฐ์ดํ„ฐ ์†Œ์Šค๊ฐ€ Steam.iterate๊ฑฐ๋‚˜ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์œผ๋กœ limit์„ ์“ฐ๋ฉด ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌํ™”๋กœ ์„ฑ๋Šฅ ๊ฐœ์„ ์„ ๊ธฐ๋Œ€ํ•  ์ˆ˜ ์žˆ๋‹ค.

์œ„ ์ฝ”๋“œ๋Š” ๋‘ ๋ฌธ์ œ๋ฅผ ๋ชจ๋‘ ์ง€๋‹ˆ๊ณ  ์žˆ๋‹ค. ๋˜ํ•œ ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌํ™”๋Š” limit์„ ๋‹ค๋ฃฐ ๋•Œ CPU ์ฝ”์–ด๊ฐ€ ๋‚จ๋Š”๋‹ค๋ฉด ์›์†Œ๋ฅผ ๋ช‡ ๊ฐœ ๋” ์ฒ˜๋ฆฌํ•œ ํ›„ ์ œํ•œ๋œ ๊ฐœ์ˆ˜ ์ดํ›„์˜ ๊ฒฐ๊ณผ๋ฅผ ๋ฒ„๋ ค๋„ ์•„๋ฌด๋Ÿฐ ํ•ด๊ฐ€ ์—†๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.

๊ทธ๋Ÿฐ๋ฐ ์ด ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ ์ƒˆ๋กญ๊ฒŒ ๋ฉ”๋ฅด์„ผ ์†Œ์ˆ˜๋ฅผ ์ฐพ์„ ๋•Œ๋งˆ๋‹ค ๊ทธ ์ „ ์†Œ์ˆ˜๋ฅผ ์ฐพ์„ ๋•Œ๋ณด๋‹ค ๋‘ ๋ฐฐ ์ •๋„ ๋” ์˜ค๋ž˜ ๊ฑธ๋ฆฐ๋‹ค. ์ฆ‰, ์›์†Œ ํ•˜๋‚˜๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋น„์šฉ์ด ๋Œ€๋Ÿ‰ ๊ทธ ์ด์ „๊นŒ์ง€์˜ ์›์†Œ ์ „๋ถ€๋ฅผ ๊ณ„์‚ฐํ•œ ๋น„์šฉ์„ ํ•ฉ์นœ ๊ฒƒ๋งŒํผ ๋“ ๋‹ค๋Š” ๋œป์ด๋‹ค. ๊ทธ๋ž˜์„œ ์œ„ ์ฝ”๋“œ์˜ ํŒŒ์ดํ”„๋ผ์ธ์• ์ž๋™ ๋ณ‘๋ ฌํ™” ์•Œ๊ณ ๋ฆฌ์ฆ˜์ด ์ œ ๊ธฐ๋Šฅ์„ ๋ชปํ•˜๊ฒŒ ๋งˆ๋น„์‹œํ‚จ๋‹ค.

ยท ๊ตํ›ˆ: ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์„ ๋งˆ๊ตฌ์žก์ด๋กœ ๋ณ‘๋ ฌํ™”ํ•˜๋ฉด ์•ˆ ๋œ๋‹ค. ์„ฑ๋Šฅ์ด ์˜คํžˆ๋ ค ๋”์ฐํ•˜๊ฒŒ ๋‚˜๋น ์งˆ ์ˆ˜ ์žˆ๋‹ค.

์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌํ™”์˜ ์˜ฌ๋ฐ”๋ฅธ ์‚ฌ์šฉ

ยท ๋Œ€์ฒด๋กœ ์ŠคํŠธ๋ฆผ ์†Œ์Šค๊ฐ€ ArrayList, HashMap, HashSet, ConcurrentHashMap์˜ ์ธ์Šคํ„ด์Šค๊ฑฐ๋‚˜ ๋ฐฐ์—ด, int ๋ฒ”์œ„, long ๋ฒ”์œ„์ผ ๋•Œ ๋ณ‘๋ ฌํ™”์˜ ํšจ๊ณผ๊ฐ€ ๊ฐ€์žฅ ์ข‹๋‹ค.

- ์ด ์ž๋ฃŒ๊ตฌ์กฐ๋“ค์€ ๋ชจ๋‘ ๋ฐ์ดํ„ฐ๋ฅผ ์›ํ•˜๋Š” ํฌ๊ธฐ๋กœ ์ •ํ™•ํ•˜๊ณ  ์†์‰ฝ๊ฒŒ ๋‚˜๋ˆŒ ์ˆ˜ ์žˆ์–ด์„œ ์ผ์„ ๋‹ค์ˆ˜์˜ ์Šค๋ ˆ๋“œ์— ๋ถ„๋ฐฐํ•˜๊ธฐ์— ์ข‹๋‹ค.

- ๋‚˜๋ˆ„๋Š” ์ž‘์—…์€ Spliterator๊ฐ€ ๋‹ด๋‹นํ•˜๊ณ , Spliterator ๊ฐ์ฒด๋Š” Stream์ด๋‚˜ Iterable์˜ spliterator ๋ฉ”์„œ๋“œ๋กœ ์–ป์–ด์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

ยท ์ด ์ž๋ฃŒ๊ตฌ์กฐ๋“ค์€ ๋ชจ๋‘ ์›์†Œ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์‹คํ–‰ํ•  ๋•Œ์˜ ์ฐธ์กฐ ์ง€์—ญ์„ฑ(locality of reference)์ด ๋›ฐ์–ด๋‚˜๋‹ค.

- ์ด์›ƒํ•œ ์›์†Œ์˜ ์ฐธ์กฐ๋“ค์ด ๋ฉ”๋ชจ๋ฆฌ์— ์—ฐ์†ํ•˜์—ฌ ์ €์žฅ๋˜์–ด ์žˆ๋‹ค๋Š” ๋œป์ด๋‹ค.

- ์ฐธ์กฐ๋“ค์ด ๊ฐ€๋ฆฌํ‚ค๋Š” ์‹ค์ œ ๊ฐ์ฒด๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์„œ๋กœ ๋–จ์–ด์ ธ ์žˆ์„ ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ๋Ÿฌ๋ฉด ์ฐธ์กฐ ์ง€์—ญ์„ฑ์ด ๋‚˜๋น ์ง„๋‹ค.

- ์ฐธ์กฐ ์ง€์—ญ์„ฑ์ด ๋‚ฎ์œผ๋ฉด ์Šค๋ ˆ๋“œ๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์ฃผ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์บ์‹œ ๋ฉ”๋ชจ๋ฆฌ๋กœ ์ „์†ก๋˜์–ด ์˜ค๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ์‹œ๊ฐ„์„ ๋ฉํ•˜๋‹ˆ ๋ณด๋‚ธ๋‹ค.

- ๋”ฐ๋ผ์„œ ์ฐธ์กฐ ์ง€์—ญ์„ฑ์„ ๋‹ค๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฒŒํฌ ์—ฐ์‚ฐ์„ ๋ณ‘๋ ฌํ™”ํ•  ๋•Œ ์•„์ฃผ ์ค‘์š”ํ•œ ์š”์†Œ๋‹ค.

- ์ฐธ์กฐ ์ง€์—ญ์„ฑ์ด ๊ฐ€์žฅ ๋›ฐ์–ด๋‚œ ์ž๋ฃŒ๊ตฌ์กฐ๋Š” ๊ธฐ๋ณธ ํƒ€์ž…์˜ ๋ฐฐ์—ด์ด๋‹ค. ๊ธฐ๋ณธ ํƒ€์ž… ๋ฐฐ์—ด์—๋Š” ๋ฐ์ดํ„ฐ ์ž์ฒด๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์— ์—ฐ์†ํ•ด์„œ ์ €์žฅ๋œ๋‹ค.

ยท ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ข…๋‹จ ์—ฐ์‚ฐ์˜ ๋™์ž‘ ๋ฐฉ์‹๋„ ๋ณ‘๋ ฌ ์ˆ˜ํ–‰ ํšจ์œจ์— ์˜ํ–ฅ์„ ์ค€๋‹ค.

- ์ข…๋‹จ ์—ฐ์‚ฐ์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…๋Ÿ‰์ด ํŒŒ์ดํ”„๋ผ์ธ ์ „์ฒด ์ž‘์—…์—์„œ ์ƒ๋‹น ๋น„์ค‘์„ ์ฐจ์ง€ํ•˜๋ฉด์„œ ์ˆœ์ฐจ์ ์ธ ์—ฐ์‚ฐ์ด๋ฉด, ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌ ์ˆ˜ํ–‰์˜ ํšจ๊ณผ๋Š” ์ œํ•œ๋œ๋‹ค.

- ๋ณ‘๋ ฌํ™”์— ์ ‘ํ•ฉํ•œ ์ข…๋‹จ ์—ฐ์‚ฐ: ๊ฐ€์žฅ ์ ํ•ฉํ•œ ๊ฒƒ์€ ์ถ•์†Œ(reduction)์ด๋‹ค. ์ถ•์†Œ๋Š” reduce ๋ฉ”์„œ๋“œ ์ค‘ ํ•˜๋‚˜ ๋˜๋Š”, min, max, count, sum ๊ฐ™์ด ์™„์„ฑ๋œ ํ˜•ํƒœ๋กœ ์ œ๊ณต๋˜๋Š” ๋ฉ”์„œ๋“œ ์ค‘ ํ•˜๋‚˜๋ฅผ ์„ ํƒํ•ด ์ˆ˜ํ–‰ํ•œ๋‹ค. any, allMatch, noneMatch ์ฒ˜๋Ÿผ ์กฐ๊ฑด์— ๋งž์œผ๋ฉด ๋ฐ”๋กœ ๋ฐ˜ํ™˜๋˜๋Š” ๋ฉ”์„œ๋“œ๋„ ๋ณ‘๋ ฌํ™”์— ์ ํ•ฉํ•˜๋‹ค.

- ๋ณ‘๋ ฌํ™”์— ๋ถ€์ ‘ํ•ฉํ•œ ์ข…๋‹จ ์—ฐ์‚ฐ: ๊ฐ€๋ณ€ ์ถ•์†Œ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋Š” Stream์˜ collect ๋ฉ”์„œ๋“œ๋Š” ๋ณ‘๋ ฌํ™”์— ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค. ์ปฌ๋ ‰์…˜๋“ค์„ ํ•ฉ์น˜๋Š” ๋ถ€๋‹ด์ด ํฌ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ยท ์ง์ ‘ ๊ตฌํ˜„ํ•œ Stream, Iterable, Collection์ด ๋ณ‘๋ ฌํ™”์˜ ์ด์ ์„ ์ œ๋Œ€๋กœ ๋ˆ„๋ฆฌ๊ฒŒ ํ•˜๋ ค๋ฉด, Spliterator ๋ฉ”์„œ๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ์žฌ์ •์˜ํ•˜๊ณ  ๊ฒฐ๊ณผ ์ŠคํŠธ๋ฆผ์˜ ๋ณ‘๋ ฌํ™” ์„ฑ๋Šฅ์„ ๊ฐ•๋„ ๋†’๊ฒŒ ํ…Œ์ŠคํŠธํ•˜๋ผ.

- ๊ณ ํšจ์œจ spliterator๋ฅผ ์ž‘์„ฑํ•˜๊ธฐ๋ž€ ์ƒ๋‹นํ•œ ๋‚œ์ด๋„์˜ ์ผ์ด๊ณ , ์ด ์ฑ…์—์„œ๋Š” ๋‹ค๋ฃจ์ง€ ์•Š๋Š”๋‹ค.

ยท ์ŠคํŠธ๋ฆผ์„ ์ž˜๋ชป ๋ณ‘๋ ฌํ™”ํ•˜๋ฉด (์‘๋‹ต ๋ถˆ๊ฐ€ ๋“ฑ) ์„ฑ๋Šฅ์ด ๋‚˜๋น ์งˆ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ, ๊ฒฐ๊ณผ ์ž์ฒด๊ฐ€ ์ž˜๋ชป๋˜๊ฑฐ๋‚˜ ์˜ˆ์ƒ ๋ชปํ•œ ๋™์ž‘์ด ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

- ๊ฒฐ๊ณผ๊ฐ€ ์ž˜๋ชป๋˜๊ฑฐ๋‚˜ ์˜ค์ž‘๋™ํ•˜๋Š” ๊ฒƒ์€ ์•ˆ์ „ ์‹คํŒจ(safety failure)๋ผ ํ•œ๋‹ค.

- ์•ˆ์ „ ์‹คํŒจ๋Š” ๋ณ‘๋ ฌํ™”ํ•œ ํŒŒ์ดํ”„๋ผ์ธ์ด ์‚ฌ์šฉํ•˜๋Š” mappers, filters, ํ”„๋กœ๊ทธ๋ž˜๋จธ๊ฐ€ ์ œ๊ณตํ•œ ๋‹ค๋ฅธ ํ•จ์ˆ˜ ๊ฐ์ฒด๊ฐ€ ๋งน์„ธ๋Œ€๋กœ ๋™์ž‘ํ•˜์ง€ ์•Š์„ ๋•Œ ๋ฒŒ์–ด์งˆ ์ˆ˜ ์žˆ๋‹ค.

- Stream ๋ช…์„ธ๋Š” ์ด๋•Œ ์‚ฌ์šฉ๋˜๋Š” ํ•จ์ˆ˜ ๊ฐ์ฒด์— ๊ด€ํ•œ ์—„์ค‘ํ•œ ๊ทœ์•ฝ์„ ์ •์˜ํ•ด๋†จ๋‹ค.

ex) Stream์˜ reduce ์—ฐ์‚ฐ์— ๊ฑด๋„ค์ง€๋Š” accumulator(๋ˆ„์ ๊ธฐ)์™€ combiner(๊ฒฐํ•ฉ๊ธฐ) ํ•จ์ˆ˜๋Š” ๋ฐ˜๋“œ์‹œ ๊ฒฐํ•ฉ๋ฒ•์น™์„ ๋งŒ์กฑํ•˜๊ณ , ๊ฐ„์„ญ๋ฐ›์ง€ ์•Š๊ณ , ์ƒํƒœ๋ฅผ ๊ฐ–์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.

- ์œ„ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ง€ํ‚ค์ง€ ๋ชปํ•ด๋„ ํŒŒ์ดํ”„๋ผ์ธ์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์ˆ˜ํ–‰ํ•œ๋‹ค๋ฉด ์˜ฌ๋ฐ”๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณ‘๋ ฌ๋กœ ์ˆ˜ํ–‰ํ•˜๋ฉด ์‹คํŒจ๋กœ ์ด์–ด์ง€๊ธฐ ์‰ฝ๋‹ค.

- ์•ž์„œ ๋ณ‘๋ ฌํ™”ํ•œ ๋ฉ”๋ฅด์„ผ ์†Œ์ˆ˜ ํ”„๋กœ๊ทธ๋žจ์€ ์™„๋ฃŒ๋˜๋”๋ผ๋„ ์ถœ๋ ฅ๋œ ์†Œ์ˆ˜์˜ ์ˆœ์„œ๊ฐ€ ์˜ฌ๋ฐ”๋ฅด์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ์ถœ๋ ฅ ์ˆœ์„œ๋ฅผ ์ˆœ์ฐจ ๋ฒ„์ „์ฒ˜๋Ÿผ ์ •๋ ฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์ข…๋‹จ ์—ฐ์‚ฐ forEach๋ฅผ forEachOrdered๋กœ ๋ฐ”๊ฟ”์ž. ์ด ์—ฐ์‚ฐ์€ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ๋“ค์„ ์ˆœํšŒํ•˜๋ฉฐ ์†Œ์ˆ˜๋ฅผ ๋ฐœ๊ฒฌํ•œ ์ˆœ์„œ๋Œ€๋กœ ์ถœ๋ ฅ๋˜๋„๋ก ๋ณด์žฅํ•ด์ค„ ๊ฒƒ์ด๋‹ค.

ยท ๋ฐ์ดํ„ฐ ์†Œ์Šค ์ŠคํŠธ๋ฆผ์ด ํšจ์œจ์ ์œผ๋กœ ๋‚˜๋ˆ ์ง€๊ณ , ๋ณ‘๋ ฌํ™”ํ•˜๊ฑฐ๋‚˜ ๋นจ๋ฆฌ ๋๋‚˜๋Š” ์ข…๋‹จ ์—ฐ์‚ฐ์„ ์‚ฌ์šฉํ•˜๊ณ , ํ•จ์ˆ˜ ๊ฐ์ฒด๋“ค๋„ ๊ฐ„์„ญํ•˜์ง€ ์•Š๋”๋ผ๋„, ํŒŒ์ดํ”„๋ผ์ธ์ด ์ˆ˜ํ–‰ํ•˜๋Š” ์ง„์งœ ์ž‘์—…์ด ๋ณ‘๋ ฌํ™”์— ๋“œ๋Š” ์ถ”๊ฐ€ ๋น„์šฉ์„ ์ƒ์‡„ํ•˜์ง€ ๋ชปํ•˜๋ฉด, ์„ฑ๋Šฅ ํ–ฅ์ƒ์€ ๋ฏธ๋ฏธํ•  ์ˆ˜ ์žˆ๋‹ค.

- ์„ฑ๋Šฅ์ด ํ–ฅ์ƒ๋ ์ง€ ์ถ”์ •ํ•ด๋ณด๋Š” ๋ฐฉ๋ฒ•: ์ŠคํŠธ๋ฆผ ์•ˆ์˜ ์›์†Œ ์ˆ˜์™€ ์›์†Œ๋‹น ์ˆ˜ํ–‰๋˜๋Š” ์ฝ”๋“œ ์ค„ ์ˆ˜๋ฅผ ๊ณฑํ•œ๋‹ค. ์ด ๊ฐ’์ด ์ตœ์†Œ ์ˆ˜์‹ญ๋งŒ์€ ๋˜์–ด์•ผ ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ๋ง›๋ณผ ์ˆ˜ ์žˆ๋‹ค.

ยท ์ŠคํŠธ๋ฆผ ๋ณ‘๋ ฌํ™”๋Š” ์˜ค์ง ์„ฑ๋Šฅ ์ตœ์ ํ™” ์ˆ˜๋‹จ์ด๋ฏ€๋กœ, ๋ณ€๊ฒฝ ์ „ํ›„๋กœ ๋ฐ˜๋“œ์‹œ ์„ฑ๋Šฅ์„ ํ…Œ์ŠคํŠธํ•˜์—ฌ ์‚ฌ์šฉํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์ธํ•ด์•ผ ํ•œ๋‹ค(์•„์ดํ…œ 67).

- ์ด์ƒ์ ์œผ๋กœ๋Š” ์šด์˜ ์‹œ์Šคํ…œ๊ณผ ํก์‚ฌํ•œ ํ™˜๊ฒฝ์—์„œ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

- ๋ณดํ†ต์€ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ๋„ ๊ณตํ†ต์˜ ํฌํฌ-์กฐ์ธ ํ’€์—์„œ ์ˆ˜ํ–‰๋˜๋ฏ€๋กœ(์ฆ‰, ๊ฐ™์€ ์Šค๋ ˆ๋“œ ํ’€์„ ์‚ฌ์šฉ), ์ž˜๋ชป๋œ ํŒŒ์ดํ”„๋ผ์ธ ํ•˜๋‚˜๊ฐ€ ์‹œ์Šคํ…œ์˜ ๋‹ค๋ฅธ ๋ถ€๋ถ„์˜ ์„ฑ๋Šฅ๊นŒ์ง€ ์•…์˜ํ–ฅ์„ ์ค„ ์ˆ˜ ์žˆ๋‹ค.

์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌํ™”์˜ ํšจ๊ณผ๊ฐ€ ์ œ๋Œ€๋กœ ๋ฐœํœ˜๋˜๋Š” ์˜ˆ

ยท ์กฐ๊ฑด์ด ์ž˜ ๊ฐ–์ถฐ์ง€๋ฉด parallel ๋ฉ”์„œ๋“œ ํ˜ธ์ถฃ ํ•˜๋‚˜๋กœ ๊ฑฐ์˜ ํ”„๋กœ์„ธ์„œ ์ฝ”์–ด ์ˆ˜์— ๋น„๋ก€ํ•˜๋Š” ์„ฑ๋Šฅ ํ–ฅ์ƒ์„ ๋งŒ๋ฝํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์Œ์€ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ ๋ณ‘๋ ฌํ™”๊ฐ€ ํšจ๊ณผ๋ฅผ ์ œ๋Œ€๋กœ ๋ฐœํœ˜ํ•˜๋Š” ์˜ˆ๋‹ค. n๋ณด๋‹ค ์ž‘๊ฑฐ๋‚˜ ๊ฐ™์€ ์†Œ์ˆ˜์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค.

// ์†Œ์ˆ˜ ๊ณ„์‚ฐ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ - ๋ณ‘๋ ฌํ™”์— ์ ํ•ฉ
static long pi(long n) {
    return LongStream.rangeClosed(2, n)
        .mapToObj(BigInteger::valueOf)
        .filter(i -> i.isProbablePrime(50))
        .count();
}

๋‹ค์Œ์€ ์œ„ ํ”„๋กœ๊ทธ๋žจ์„ ๋ณ‘๋ ฌํ™” ๋ฒ„์ „์œผ๋กœ ๋ณ€๊ฒฝํ•œ ๊ฒƒ์ด๋‹ค. parallel() ํ˜ธ์ถœ ํ•˜๋‚˜๋ฅผ ์ถ”๊ฐ€ํ•œ ๊ฒƒ๋งŒ์œผ๋กœ ์ž‘์—… ์‹œ๊ฐ„์ด ์ƒ๋‹นํžˆ ๊ฐ์†Œํ•œ๋‹ค.

// ์†Œ์ˆ˜ ๊ณ„์‚ฐ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ - ๋ณ‘๋ ฌํ™” ๋ฒ„์ „
static long pi(long n) {
    return LongStream.rangeClosed(2, n)
        .parallel() // ๊ธฐ์กด ๋กœ์ง์— ์ถ”๊ฐ€๋œ ๋ถ€๋ถ„
        .mapToObj(BigInteger::valueOf)
        .filter(i -> i.isProbablePrime(50))
        .count();
}

๋ฌด์ž‘์œ„ ์ˆ˜์˜ ๋ณ‘๋ ฌํ™”: SplittableRandom vs ThreadRandom vs Random

ยท ๋ฌด์ž‘์œ„ ์ˆ˜๋“ค๋กœ ์ด๋ค„์ง„ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌํ™”ํ•˜๋ ค๋ฉด ThreadLocalRandom(๋˜๋Š” Random)๋ณด๋‹ค๋Š” SplittableRandom ์ธ์Šคํ„ด์Šค๋ฅผ ์ด์šฉํ•˜์ž.

- ํ•ด๋‹น ํด๋ž˜์Šค๋Š” ์ •ํ™•ํžˆ ์ด๋Ÿด ๋•Œ ์“ฐ๊ณ ์ž ์„ค๊ณ„๋œ ๊ฒƒ์ด๋ผ ๋ณ‘๋ ฌํ™”ํ•˜๋ฉด ์„ฑ๋Šฅ์ด ์„ ํ˜•์œผ๋กœ ์ฆ๊ฐ€ํ•œ๋‹ค.

ยท ThreadRandom์€ ๋‹จ์ผ ์Šค๋ ˆ๋“œ์—์„œ ์“ฐ๊ณ ์ž ๋งŒ๋“ค์–ด์กŒ๋‹ค.

- ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์šฉ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋กœ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, SplittableRandom๋งŒํผ ๋น ๋ฅด์ง€๋Š” ์•Š๋‹ค.

ยท Random์€ ๋ชจ๋“  ์—ฐ์‚ฐ์„ ๋™๊ธฐํ™”ํ•˜๋ฏ€๋กœ, ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•˜๋ฉด ์ตœ์•…์˜ ์„ฑ๋Šฅ์„ ๋ณด์ธ๋‹ค.

Last updated