CHAP01 - Modern-Java-in-Action/Online-Study GitHub Wiki

1.1 ์ฃผ๋ชฉํ•  ๋งŒํ•œ ์ด์•ผ๊ธฐ

Java 8์€ ์—ญ์‚ฌ์ƒ ๊ฐ€์žฅ ํฐ ๋ณ€ํ™”๊ฐ€ ์žˆ์—ˆ๋‹ค. Java 9 (๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ธ ๋ณ‘๋ ฌ ์‹คํ–‰๊ธฐ๋ฒ• ์ง€์›. RxJava)๋Š” ํš๊ธฐ์ ์ด๊ฑฐ๋‚˜ ์ƒ์‚ฐ์„ฑ์ด ๋ฐ”๋€”์ •๋„๋Š” ์•„๋‹ˆ์—ˆ๊ณ  ์ž๋ฐ” 10์—์„œ๋Š” type inference ๊ด€๋ จํ•ด ์•ฝ๊ฐ„์˜ ๋ณ€ํ™”๊ฐ€ ์žˆ์—ˆ๋‹ค.

  • Reactive Programing์ด๋ž€? ์ผ€๋นˆ ์œ ํˆฌ๋ธŒ
    • ํด๋ผ์ด์–ธํŠธ-์„œ๋ฒ„ ๋™๊ธฐ์‹ ๊ตฌ์กฐ๊ฐ€ ๋Œ€๋ถ€๋ถ„์ด์—ˆ๋Š”๋ฐ, ๊ทœ๋ชจ๊ฐ€ ์ปค์ง์— ๋”ฐ๋ผ ๋ณต์žกํ•œ ๋น„๋™๊ธฐ์‹ ์š”์ฒญ์„ ์ฒ˜๋ฆฌํ•ด์•ผ๋˜๋Š” ์ƒํ™ฉ์ด ์™”๋‹ค. ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ด๊ฒƒ์„ ํšจ๊ณผ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ๋„์ž…๋˜์—ˆ๋‹ค.
    • ์ •์˜: ๋ณ€ํ™”์˜ ์ „ํŒŒ์™€ ๋ฐ์ดํ„ฐ ํ๋ฆ„๊ณผ ๊ด€๋ จ๋œ ์„ ์–ธ์  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„.
      • ์›๋ž˜ ์ž๋ฐ”๋Š” imperative ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์‚ฌ์šฉํ–ˆ์—ˆ์Œ.
      • imperative (๋ช…๋ นํ˜•)๊ณผ declarative (์„ ์–ธ์ ) ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ฐจ์ด๋Š”?
        • declarative: ์ถ”์ƒํ™” ํ•˜๋Š”๊ฒƒ (e.g., ์ŠคํŠธ๋ฆผ) (blog)

8๋ฒ„์ „ ์ด์ „์˜ ์ฝ”๋“œ์™€ ๋น„๊ต

//์ž๋ฐ” 8 ์ด์ „
Collections.sort(inventory, new Comparator<Apple>() {
    public int compare(Apple a1, Apple a2){
        return a1.getWeight().compareTo(a2.getWeight());
    }
});

//์ž๋ฐ” 8
// ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ์— ๋ฉ”์„œ๋“œ๋ฅผ ๋„˜๊ธฐ๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ด์ง. 
inventory.sort(comparing(Apple::getWeight));
  • ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ์ž๋ฐ” ๋ฒ„์ „

  • ์ž๋ฐ” ๋ฒ„์ „๋“ค ์„ค๋ช…

    • JDK, J2EE, J2SE ์ฐจ์ด๊ฐ€ ๋ญ์ฃ ?
      • JDK - ๊ธฐ๋ณธ ์ž๋ฐ” kit, ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ
      • J2EE - ์„œ๋ฒ„ ์‚ฌ์ด๋“œ
      • J2SE(=์˜ค๋Š˜๋‚  Java SE) - Swing, Applets, etc
    • ์ž๋ฐ” 8 ์ด์ „ - ์ฝ”์–ด๋“ค์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์“ฐ๋ ˆ๋“œ๋ฅผ ์ž˜ ํ™œ์šฉํ•˜๋ผ๊ณ  ํ•˜๋Š”๋ฐ, ์‹ค์ƒ ์“ฐ๋ ˆ๋“œ๋ฅผ ๋‹ค๋ฃจ๋Š” ์ผ์€ error-proneํ•˜๊ณ  ์–ด๋ ต๋‹ค.
    • ์ž๋ฐ” 5 - ์“ฐ๋ ˆ๋“œํ’€์ด๋‚˜ ๋™์‹œ์ ์ธ ์ปฌ๋ ‰์…˜๋“ค๊ณผ ๊ฐ™์€ ๋ธ”๋ก๋“ค์„ ์ถ”๊ฐ€
    • ์ž๋ฐ” 7 - fork/join ํ”„๋ ˆ์ž„์›Œํฌ์™€ ๋ณ‘๋ ฌ์„ฑ ๋“ฑ์žฅ์œผ๋กœ ์ข€ ๋” ์‹ค์šฉ์ ์ด์ง€๋งŒ ์—ฌ์ „ํžˆ ์–ด๋ ต.
    • ์ž๋ฐ” 8 ๋ถ€ํ„ฐ - ์‚ฌ์šฉํ•˜๊ธฐ ์‰ฌ์šด ๋ณ‘๋ ฌ์„ฑ ๋“ฑ์žฅ
  • ๊ฐ€์žฅ ํฐ ๋ณ€ํ™”๋ฅผ ๊ฐ€์ง„ ์ž๋ฐ” 8์˜ ์ค‘์š”ํ•œ ์ถ”๊ฐ€์‚ฌํ•ญ๋“ค

    • Streams API
      • ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ, synchronized๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.
    • Techniques for passing code to methods
      • behavior parameterization์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๊ณ , ๋– ์˜ค๋ฅด๋Š” ์ƒˆ๋กœ์šด ์ปดํ“จํ„ฐ ์•„ํ‚คํ…์ฒ˜๋กœ์ธ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ์œ„๋ ฅ์„ ๋ฐœํœ˜ํ•œ๋‹ค.
    • Default methods in interface
      • ์ธํ„ฐํŽ˜์ด์Šค ๋‚ด๋ถ€์—์„œ๋„ ๋กœ์ง์ด ํฌํ•จ๋œ ๋ฉ”์†Œ๋“œ๋ฅผ ์„ ์–ธ ๊ฐ€๋Šฅ
      • ๋„์ž… ์ด์œ : ํ•˜์œ„ ํ˜ธํ™˜์„ฑ

1.2 ์™œ ์ž๋ฐ”๋Š” ์•„์ง๋„ ๋ณ€ํ•˜๊ณ  ์žˆ๋Š”๊ฐ€?

์ˆ˜๋ฐฑ๊ฐœ์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด๊ฐ€ ์žˆ๊ณ  ์‚ด์•„๋‚จ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ง„ํ™”๊ฐ€ ํ•„์š”ํ•˜๋‹ค. **C๋‚˜ C++**์˜ ๊ฒฝ์šฐ๋Š” ์˜ค๋ž˜๋๊ณ  ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์•ˆ์ •์„ฑ์ด ๋ถ€์กฑํ•˜์ง€๋งŒ runtime footprint๊ฐ€ ์ž‘๋‹ค๋Š” ๊ฐ•์ ์ด ์žˆ์–ด OS๋ฅผ ๊ฐœ๋ฐœํ•˜๊ฑฐ๋‚˜ ์ž„๋ฒ ๋””๋“œ ์‹œ์Šคํ…œ์—์„œ ์•„์ง๋„ ๋งŽ์ด ์‚ฌ์šฉ๋˜๊ณ  ์žˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  Algol, COBOL, Pascal ๊ฐ™์€ ์ง„ํ™” ํ•˜์ง€ ๋ชปํ•œ ์–ธ์–ด๋“ค์€ ์˜ค๋Š˜๋‚  ์‚ด์•„๋‚จ์ง€ ๋ชปํ•˜์˜€๋‹ค. Java๊ฐ€ ์ต์ˆ™ํ•˜์ง€ ์•Š์•˜๋˜ ํ…Œ๋ผ๋ฐ”์ดํŠธ ๋‹จ์œ„์˜ ๋น…๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ƒˆ๋กœ์šด ๊ฐœ๋… ๋„์ž…๋„ ํ•„์š”ํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค (์˜ˆ, ๋ณ‘๋ ฌํ”„๋กœ์„ธ์‹ฑ) . ์ฆ‰, ์‚ด์•„๋‚จ๊ธฐ ์œ„ํ•ด์„œ๋Š” ์ง„ํ™”๊ฐ€ ํ•„์š”ํ•˜๋‹ค.

1.2.1 ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ์ƒํƒœ๊ณ„์—์„œ ์ž๋ฐ” ์œ„์น˜

์ž๋ฐ”๋Š” ์บก์Аํ™”์™€ ๊ฐ™์€ ๊ฐ์ฒด์ง€ํ–ฅ ๋ชจ๋ธ๊ณผ write-once and run-anywhere์˜ ์ปจ์…‰ ๋•๋ถ„์—” ์ž…์ง€๋ฅผ ๋ฐœ์ „ํ•ด์™”๋‹ค.

์ด ๋ฐ‘์œผ๋กœ ์ž๋ฐ” 8์—์„œ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์˜ 3๊ฐ€์ง€ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ฐœ๋…์„ ์ž์„ธํžˆ ๋ฐฐ์›Œ๋ณด์ž.

1.2.2 ์ŠคํŠธ๋ฆผ ํ”„๋กœ์„ธ์‹ฑ

  • ์ŠคํŠธ๋ฆผ = ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์”ฉ ์ƒ์„ฑ๋˜๋Š” ์ผ๋ จ์˜ ๋ฐ์ดํ„ฐ ํ•ญ๋ชฉ
  • ์ž์„ธํ•œ ๋ถ€๋ถ„์€ 4~7์žฅ์—์„œ ์„ค๋ช…ํ•œ๋‹ค.
  • ์œ ๋‹‰์Šค ๊ธฐ๋ฐ˜๋„ ์ŠคํŠธ๋ฆผ ํ”„๋กœ์„ธ์‹ฑํ•˜๊ณ  ๋น„์Šท
// ์œ ๋‹‰์Šค ๋ช…๋ น์–ด ํŒŒ์ดํ”„(|)๋ฅผ ํ†ตํ•ด ์—ฐ๊ฒฐ 
// ํŒŒ์ผ ๋‘๊ฐœ๋ฅผ ํ•ฉ์ณ ๋ชจ๋“  ๋ฌธ์ž๋ฅผ ์†Œ๋ฌธ์ž๋กœ ๋ฐ”๊พธ๊ณ  ์ •๋ ฌํ›„ ๋’ค 3์ค„์„ ๊ฐ€์ ธ์˜จ๋‹ค.
// ๋ช…๋ น์„ ์ˆœ์ฐจ์ ์ด ์•„๋‹Œ cat, tr, sort, tail ๊ฐ๊ฐ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•œ๋‹ค.
cat file1 file2 | tr "[A-Z]" "[a-z]" | sort | tail -3
// ์ฝ”๋“œ ์„ค๋ช…: ๋‘ํŒŒ์ผ์„ ์—ฐ๊ฒฐํ•ด์„œ ์ŠคํŠธ๋ฆผ ์ƒ์„ฑ -> ๋ฌธ์ž๋ฅผ ๋ฒˆ์—ญ -> ํ–‰ ์ •๋ ฌ -> ๋งˆ์ง€๋ง‰ 3์ค„
  • ๋˜ ๋‹ค๋ฅธ ๋น„์Šทํ•œ ์‚ฌ๋ก€: ์ž๋™์ฐจ ์กฐ๋ฆฝ ๋ผ์ธ
  • ์ž๋ฐ” ์ŠคํŠธ๋ฆผ ํŠน์ง•: ์Šค๋ ˆ๋“œ ์ด์šฉํ•œ ๋ณต์žกํ•œ ์ž‘์—…์„ ์ถ”๊ฐ€ํ•˜์ง€ ์•Š๊ณ ๋„ ๋ณ‘๋ ฌ์„ฑ์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

1.2.3 ๋™์ž‘ ํŒŒ๋ผ๋ฏธํ„ฐํ™”(Behavior Parameterization)๋ฅผ ์ด์šฉํ•ด ๋ฉ”์„œ๋“œ์— ์ฝ”๋“œ ๋ณด๋‚ด๊ธฐ

  • ์ž๋ฐ” 8 ์ด์ „์—๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค๋ฅธ ๋ฉ”์„œ๋“œ๋กœ ์ „๋‹ฌํ•  ๋ฐฉ๋ฒ•์ด ์—†์—ˆ๋‹ค.
  • 2, 3์žฅ์—์„œ ์ž์„ธํžˆ ๋‹ค๋ฃฌ๋‹ค.

์ฐธ๊ณ , ์˜ค๋Š˜๋‚  ์„œ๋ธŒ์‹œ์Šคํ…œ์„ ๋‹ด๋Š” ํฐ์‹œ์Šคํ…œ ๋””์ž์ธ์ด ์ฃผ๋กœ ์‚ฌ์šฉ๋˜๋Š”๋ฐ, ๋””ํดํŠธ๋ฉ”์†Œ๋“œ์™€ ๋ชจ๋“ˆ๋“ค์„ ๋„์ž…ํ•ด์„œ ํ•ด๊ฒฐํ•˜์˜€๋‹ค.

1.2.4 ๋ณ‘๋ ฌ์„ฑ(Parallelism)๊ณผ ๊ณต์œ  ๊ฐ€๋ณ€ ๋ฐ์ดํ„ฐ (Shared Mutable Data)

  • ์•ˆ์ „ํ•˜๊ฒŒ ๋™์‹œ์— ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ์„œ๋กœ ๊ณต์œ ๋œ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜์ง€ ์•Š์•„์•ผ ํ•œ๋‹ค.
  • ๊ณต์œ ๋œ ๋ณ€์ˆ˜๋‚˜ ๊ฐ์ฒด๊ฐ€ ์žˆ์œผ๋ฉด ๋ณ‘๋ ฌ์„ฑ์— ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.
  • ์ ‘๊ทผํ•  ์ˆ˜ ์—†๊ฒŒ ๋งŒ๋“  ํ•จ์ˆ˜๋ฅผ pure, side-effect-free, stateless ํ•จ์ˆ˜๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • 18, 19์žฅ์—์„œ ์ž์„ธํžˆ ๋‹ค๋ฃฌ๋‹ค.

1.2.5 ์ž๋ฐ” ์ง„ํ™”์˜ ํ•„์š”์„ฑ

  • ์ž๋ฐ”๊ฐ€ ์ง„ํ™”ํ•˜๋ฉด์„œ...
  • ํŽธ๋ฆฌํ•จ ์ค€๋‹ค.
    • ์ œ๋„ˆ๋ฆญ์ด ๋‚˜์˜ค๋ฉด์„œ, ๋ฆฌ์ŠคํŠธ ์œ ํ˜• ํŒŒ์•…์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์ปดํŒŒ์ผ์„ ํ• ๋•Œ ๋”๋งŽ์€ ์—๋Ÿฌ๋ฅผ ๊ฒ€์ถœํ•  ์ˆ˜ ์žˆ๋Š” ํŽธ๋ฆฌํ•จ์„ ์ฃผ์—ˆ๋‹ค.
  • (OOP์˜) ํ‹€์— ๋ฐ•ํžŒ iterator ๋Œ€์‹  (ํ•จ์ˆ˜ํ˜•์˜) for-each ๋ฃจํ”„๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.
  • ๊ฐ์ฒด์ง€ํ–ฅ๊ณผ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์˜ ๋‘๊ฐ€์ง€ ์žฅ์ ์„ ๋ชจ๋‘ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋˜์—ˆ๋‹ค.
  • ์š”์•ฝ, ํŽธ๋ฆฌํ•ด์ง.

1.3 ์ž๋ฐ”์—์„œ์˜ ํ•จ์ˆ˜

  • ํ”„๋กœ๊ทธ๋ž˜๋ฐ์—์„œ ํ•จ์ˆ˜๋Š” ๋ฉ”์„œ๋“œ ํŠนํžˆ static ๋ฉ”์„œ๋“œ์™€ ๊ฐ™์€ ์˜๋ฏธ๋กœ ์‚ฌ์šฉ๋œ๋‹ค. (์ดํ•ด x)
  • ์ด์—๋”ํ•ด, ์ž๋ฐ”์—์„œ๋Š” ์ˆ˜ํ•™์ ์ธ ํ•จ์ˆ˜์ฒ˜๋Ÿผ ์‚ฌ์šฉ๋˜๋ฉฐ ๋ถ€์ž‘์šฉ์„ ์ผ์œผํ‚ค์ง€ ์•Š๋Š” ํ•จ์ˆ˜๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
  • ํ•จ์ˆ˜์™€ ๋ฉ”์„œ๋“œ ์šฉ์–ด์ ์ธ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.

1.3.1 ๋ฉ”์„œ๋“œ์™€ ๋žŒ๋‹ค๋ฅผ 1๊ธ‰ ์‹œ๋ฏผ์œผ๋กœ

  • ๊ธฐ์กด ์ž๋ฐ”์—์„œ ๋ฉ”์„œ๋“œ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์€ ์—†์—ˆ๋‹ค.
  • ๋ฉ”์„œ๋“œ๋ฅผ ๊ฐ’์œผ๋กœ ์ทจ๊ธ‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์€, ์ŠคํŠธ๋ฆผ ๊ฐ™์€ ๋‹ค๋ฅธ ์ž๋ฐ” 8๊ธฐ๋Šฅ์˜ ํ† ๋Œ€๋ฅผ ์ œ๊ณตํ–ˆ๋‹ค.
  • 8๋ฒ„์ „์—์„œ ๋ฉ”์„œ๋“œ๊ฐ€ 2๊ธ‰๊ฐ’์ด ์•„๋‹Œ 1๊ธ‰ ๊ฐ’์ด ๋˜์—ˆ๋‹ค.

๊ทธ ๋ฐฉ๋ฒ•๋“ค์„ ํ™•์ธํ•ด๋ณด์ž.

๋ฉ”์„œ๋“œ ์ฐธ์กฐ ์˜ˆ์ œ ์ฝ”๋“œ

// 8 ๋ฒ„์ „ ์ด์ „
// FileFilter๋ฅผ ๋ฐฉ๋ฒ•์ด ์—†์–ด, ์ธ์Šคํ„ด์Šคํ™”ํ•˜์˜€๋‹ค.
File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
    public boolean accept(File file) {
        return file.isHidden();
    }
});

// 8 ๋ฒ„์ „ 
// ::์€ ๋ฉ”์†Œ๋“œ ์ฐธ์กฐ 
File[] hiddenFiles = new File(".").listFiles(File::isHidden);
  • ์—ฌ๊ธฐ์„  ๋„˜๊ฒจ์ง€๋Š” isHidden์„ ๋ฉ”์„œ๋“œ๊ฐ€ ์•„๋‹Œ ํ•จ์ˆ˜๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

1.3.2 ์ฝ”๋“œ ์ „๋‹ฌ ์˜ˆ์ œ

  • Predicate ์‚ฌ์šฉ์œผ๋กœ ์ค‘๋ณต ์ฝ”๋“œ๊ฐ€ ์‚ฌ๋ผ์ง€๋Š” ์˜ˆ์ œ.
// ์ดˆ๋ก์ƒ‰ ์‚ฌ๊ณผ๋ฆฌ์ŠคํŠธ๋งŒ ๊ฐ€์ ธ์˜ฌ๋•Œ  
public static List<Apple> filterGreenApples(List<Apple> inventory) {
    List<Apple> result = new ArrayList<>();
    for (Apple apple: inventory){
        if (GREEN.equals(apple.getColor())) { 
            result.add(apple);
        }
    }
    return result;
}

// ๋ฌด๊ฒŒ 150 ์ด์ƒ์ด ๋˜๋Š” ์‚ฌ๊ณผ๋งŒ ๊ฐ€์ ธ์˜ฌ๋•Œ (์œ„์— ์ฝ”๋“œ ๋ณต๋ถ™ ํ›„ ์ˆ˜์ •)
public static List<Apple> filterHeavyApples(List<Apple> inventory) {
    List<Apple> result = new ArrayList<>();
    for (Apple apple: inventory){
        if (apple.getWeight() > 150) {
            result.add(apple);
        }
    }
    return result;
}

// ์œ„๊ฐ™์ด ๋ณต๋ถ™ํ•˜๋Š” ์ฝ”๋“œ๋Š” ๋ฒ„๊ทธ๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ชจ๋“  ์ฝ”๋“œ ์ˆ˜์ •์ด ํ•„์š”ํ•˜๊ฒŒ ๋œ๋‹ค.
// ์•„๋ž˜์™€ ๊ฐ™์ด ์งค๊ฒฝ์šฐ ์ถ”๊ฐ€๊ฐ€ ์šฉ์ดํ•˜๋‹ค. 
public static boolean isGreenApple(Apple apple) {
    return GREEN.equals(apple.getColor());
}
public static boolean isHeavyApple(Apple apple) {
    return apple.getWeight() > 150;
}
public interface Predicate<T>{
    boolean test(T t);
}
static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
    List<Apple> result = new ArrayList<>();
    for (Apple apple: inventory){
        if (p.test(apple)) {
            result.add(apple);
        }
    }
    return result;
}

// ์‚ฌ์šฉ ์ฝ”๋“œ 
filterApples(inventory, Apple::isGreenApple); 
filterApples(inventory, Apple::isHeavyApple);

1.3.3 ๋ฉ”์„œ๋“œ ์ „๋‹ฌ ๋ง๊ณ  ๋žŒ๋‹ค๋ฅผ ์ „๋‹ฌํ•  ๊ฒฝ์šฐ

  • ํ•œ๋‘๋ฒˆ๋งŒ ์‚ฌ์šฉํ•  ๋ฉ”์„œ๋“œ๋ฅผ ๋งค๋ฒˆ ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ๊ท€์ฐฎ์€ ์ผ์ด๋‹ค.
  • ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋” ๊ฐ„๊ฒฐํ•ด์ง„๋‹ค.
  • ๋ณต์žกํ•œ ์ˆ˜ํ–‰์‹œ, ๋žŒ๋‹ค ์‚ฌ์šฉ๋ณด๋‹ค๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•˜๊ณ  ์‚ฌ์šฉํ•œ๋‹ค.
filterApples(inventory, (Apple a) -> GREEN.equals(a.getColor()) );
filterApples(inventory, (Apple a) -> a.getWeight() > 150 );
filterApples(inventory, (Apple a) -> a.getWeight() < 80 || RED.equals(a.getColor()) );

1.4 ์ŠคํŠธ๋ฆผ

  • ์ŠคํŠธ๋ฆผ API๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ปฌ๋ ‰์…˜ API์™€๋Š” ์ƒ๋‹นํžˆ ๋‹ค๋ฅธ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ŠคํŠธ๋ฆผ API์—์„œ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‚ด๋ถ€์—์„œ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ์ฒ˜๋ฆฌ๋œ๋‹ค. (internal iteration)
// ๋ฆฌ์ŠคํŠธ์—์„œ 1000 ์ด์ƒ ๊ฑฐ๋ž˜๋งŒ ํ•„ํ„ฐ๋งํ•œ ๋‹ค์Œ ํ†ตํ™”๋กœ ๊ฒฐ๊ณผ๋ฅผ ๊ทธ๋ฃนํ™”ํ•  ๊ฒฝ์šฐ
// ๋งŽ์€ boilerplate๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.
Map<Currency, List<Transaction>> transactionsByCurrencies = new HashMap<>();
for (Transaction transaction : transactions) {
    if(transaction.getPrice() > 1000){
        Currency currency = transaction.getCurrency();
        List<Transaction> transactionsForCurrency =
            transactionsByCurrencies.get(currency);
        if (transactionsForCurrency == null) {
            transactionsForCurrency = new ArrayList<>();
            transactionsByCurrencies.put(currency, transactionsForCurrency);
        }
        transactionsForCurrency.add(transaction);
    }
}

// ํ•˜์ง€๋งŒ ์ŠคํŠธ๋ฆผ api๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ์ฝ”๋“œ๋Ÿ‰์„ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.
import static java.util.stream.Collectors.groupingBy;
Map<Currency, List<Transaction>> transactionsByCurrencies =
    transactions.stream()
    .filter((Transaction t) -> t.getPrice() > 1000)
    .collect(groupingBy(Transaction::getCurrency));

1.4.1 ๋ฉ€ํ‹ฐ์“ฐ๋ ˆ๋”ฉ์˜ ์–ด๋ ค์›€

  • ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋”ฉ ํ™˜๊ฒฝ์—์„œ ๊ฐ๊ฐ์˜ ์Šค๋ ˆ๋“œ๋Š” ๋™์‹œ์— ๊ณต์œ ๋œ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐฑ์‹ ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ์ด๋กœ์จ ์Šค๋ ˆ๋“œ๋ฅผ ์ž˜ ์ œ์–ดํ•˜์ง€ ๋ชปํ•˜๋ฉด ๋ฐ์ดํ„ฐ ๊ฐ’์ด ์ด์ƒํ•œ ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ”๋€” ์ˆ˜ ์žˆ๋Š” ์ƒํ™ฉ์ด ์ƒ๊ธด๋‹ค.
  • ์ŠคํŠธ๋ฆผAPI๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด์„œ ๋ฐ˜๋ณต์ ์ธ ์ฝ”๋“œ๋ฌธ์ œ์™€ ์–ด๋ ค์šด ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ™œ์šฉ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜์˜€๋‹ค.
  • Forking Step - ๋‘ CPU๊ฐ ๊ฐ๊ฐ ์•ž๋’ค๋ฅผ ๋ถ„๋‹ดํ•ด ์ฒ˜๋ฆฌํ•œ๋‹ค.
  • ์ปฌ๋ ‰์…˜์€ ์–ด๋–ป๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์ ‘๊ทผํ• ์ง€์— ์ค‘์ , ์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ์— ์–ด๋–ค ๊ณ„์‚ฐ์„ ํ• ๊ฒƒ์ธ์ง€ ๋ฌ˜์‚ฌํ•˜๋Š”๊ฒƒ์— ์ค‘์ ์„ ๋‘”๋‹ค.
  • ์ปฌ๋ ‰์…˜์„ ๊ฐ€์žฅ ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ• - ์ปฌ๋ ‰์…˜์„์„ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ”๊พธ๊ณ  ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ, ๋ฆฌ์ŠคํŠธ๋กœ ๋‹ค์‹œ ๋ณต์›ํ•œ๋‹ค.
  • 7์žฅ์—์„œ ๋ณ‘๋ ฌ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์™€ ์„ฑ๋Šฅ ์ž์„ธํžˆ ๋‹ค๋ฃฌ๋‹ค.
// ์ˆœ์ฐจ์ฒ˜๋ฆฌ ๋ฐฉ์‹ 
import static java.util.stream.Collectors.toList;
List<Apple> heavyApples =
    inventory.stream().filter((Apple a) -> a.getWeight() > 150)
    .collect(toList());

// ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ ๋ฐฉ์‹ 
import static java.util.stream.Collectors.toList;
List<Apple> heavyApples =
    inventory.parallelStream().filter((Apple a) -> a.getWeight() > 150)
    .collect(toList());

1.5 ๋””ํดํŠธ ๋ฉ”์„œ๋“œ์™€(Default methods) ์ž๋ฐ” ๋ชจ๋“ˆ

  • ์™ธ๋ถ€์—์„œ ๋งŒ๋“ค์–ด์ง„ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŽ์ด ์‹œ์Šคํ…œ์„ ๊ตฌ์ถ•ํ•œ๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค ๋ณ€๊ฒฝ์‹œ, ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๋ชจ๋“  ํด๋ž˜์Šค์˜ ๊ตฌํ˜„์„ ๋ฐ”๊ฟ”์•ผ ํ–ˆ๋‹ค. (๊ณ ํ†ต์Šค๋Ÿฌ์šด ์ž‘์—…)
  • ์ด ๋ฌธ์ œ๋ฅผ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ํ•ด๊ฒฐํ•ด์ค€๋‹ค. (13์žฅ์—์„œ ์ž์„ธํžˆ)
  • ์ž๋ฐ” 9์˜ ๋ชจ๋“ˆ ์‹œ์Šคํ…œ์€ ๋ชจ๋“ˆ์„ ์ •์˜ํ•˜๋Š” ๋ฌธ๋ฒ• ์ œ๊ณตํ•œ๋‹ค.
    • JAR ๊ฐ™์€ ์ปดํฌ๋„ŒํŠธ์— ๊ตฌ์กฐ๋ฅผ ์ ์šฉ๊ฐ€๋Šฅ. (14์žฅ์—์„œ ์ž์„ธํžˆ)
  • ๋ฏธ๋ž˜์— ํ”„๋กœ๊ทธ๋žจ์ด ์‰ฝ๊ฒŒ ๋ณ€ํ™”ํ•  ์ˆ˜ ์ž‡๋Š” ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜๋Š” ๊ธฐ๋Šฅ์ด๋ผ ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.

์‚ฌ๋ก€๋กœ, ์•„๋ž˜ ์ฝ”๋“œ๋Š” List๋Š” ์ž๋ฐ” 8 ์ด์ „์— stream์ด๋‚˜ parallelStream ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์•„ ์ปดํŒŒ์ผ์ด ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด, Collection์— ์œ„ 2๊ฐœ๋ฅผ default ๋ฉ”์„œ๋“œ๋กœ ์ถ”๊ฐ€ํ•˜์˜€๋‹ค.

List<Apple> heavyApples1 =
    inventory.stream().filter((Apple a) -> a.getWeight() > 150)
    .collect(toList());
List<Apple> heavyApples2 =
    inventory.parallelStream().filter((Apple a) -> a.getWeight() > 150)
    .collect(toList());

์ž๋ฐ” 8์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด List ์ธํ„ฐํŽ˜์ด์Šค์— sort ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

// ์˜ˆ์‹œ ์ฝ”๋“œ 
default void sort(Comparator<? super E> c) {
    Collections.sort(this, c);
}

์—ฌ๋Ÿฌ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์„๋•Œ ๋™์ผํ•œ ๋‹ค์ค‘ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•  ์ˆ˜ ์žˆ๊ธฐ์—, ์ด๊ฒƒ์€ ๋‹ค์ค‘์ƒ์†์ด ํ—ˆ์šฉ๋œ๋‹ค๋Š” ์–˜๊ธฐ์ธ๊ฐ€? ์–ด๋А์ •๋„ ๊ทธ๋ ‡๋‹ค. ์ด ์–˜๊ธฐ๋Š” 9์žฅ์—์„œ ๋‹ค์ด์•„๋ชฌ๋“œ ์ƒ์† ๋ฌธ์ œ ํ”ผํ•˜๋Š” ๋ฐฉ๋ฒ•์—์„œ ๋‹ค๋ฃฌ๋‹ค.

1.6 ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ ๋ถ€ํ„ฐ์˜จ ์ข‹์€ ์ƒ๊ฐ๋“ค

  • ์‚ดํŽด๋ณธ ํ•จ์ˆ˜ํ˜• ํ•ต์‹ฌ์  2๊ฐ€์ง€ ํŠน์ง•
    • ๋ฉ”์„œ๋“œ์™€ ๋žŒ๋‹ค๋ฅผ 1๊ธ‰๊ฐ’์œผ๋กœ ์‚ฌ์šฉ.
    • ๊ฐ€๋ณ€ ๊ณต์œ  ์ƒํƒœ๊ฐ€ ์—†๋Š” ๋ณ‘๋ ฌ ์‹คํ–‰์„ ์ด์šฉํ•ด ์•ˆ์ „ํ•˜๊ฒŒ ํ•จ์ˆ˜๋‚˜ ๋ฉ”์„œ๋“œ ํ˜ธ์ถœ ๊ฐ€๋Šฅ.
    • ์˜ˆ๋ฅผ๋“ค์–ด, Stream API๋Š” ์ด 2๊ฐ€์ง€๋ฅผ ๋‹ค ํ™œ์šฉํ•œ๋‹ค.
  • ํ•˜์Šค์ผˆ๊ณผ ๊ฐ™์€ ํ•จ์ˆ˜ํ˜• ์–ธ์–ด๋Š” null์„ ํšŒํ”ผํ•˜๋Š” ๊ธฐ๋Šฅ์ด ์žˆ๋‹ค.
  • ๋„์ฐธ์กฐ๋ฅผ ๋ฐœ๋ช…ํ•œ๊ฒƒ์€ ๋ผˆ์•„ํ”ˆ ์‹ค์ˆ˜ (Tony Hoare)
  • ์ด์— ๋Œ€์‘ํ•˜๊ธฐ ์œ„ํ•œ, ์ž๋ฐ”์˜ ์„ ํƒ Optional (11์žฅ์—์„œ ์ž์„ธํžˆ)
  • null์— ๋Œ€์‘ํ•˜๊ธฐ์œ„ํ•œ ๋‹ค๋ฅธ ๋ฐฉ๋ฒ• ํŒจํ„ด๋งค์นญ์ด ์žˆ๋Š”๋ฐ, ์ž๋ฐ”์—์„œ๋Š” ์•„์ง ๋ถˆ์™„์ „ (19์žฅ์—์„œ ์ž์„ธํžˆ)

์ •๋ฆฌ

  • ์ž๋ฐ” 8์˜ ํ•ต์‹ฌ์ ์ธ ์ถ”๊ฐ€๋Š” ํฅ๋ฏธ๋กœ์šด ์ƒˆ๋กœ์šด ์ปจ์…‰๋“ค๊ณผ ๊ธฐ๋Šฅ์„ ๊ฐ„๊ฒฐํ•˜๊ณ  ํšจ์œจ์ ์œผ๋กœ ์ž‘์„ฑํ•˜๊ฒŒ ํ•œ๋‹ค.
  • 8๋ฒ„์ „ ์ด์ „์—๋Š” ๋ฉ€ํ‹ฐ์ฝ”์–ด ํ”„๋กœ์„ธ์„œ๋Š” ์ง€์›์ด ๋˜์ง€ ์•Š์•˜๋‹ค.
  • ํ•จ์ˆ˜๋Š” ์ผ๊ธ‰ ์‹œ๋ฏผ์ด๋‹ค; ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋–ป๊ฒŒ ํ•จ์ˆ˜ํ˜• ๊ฐ’์œผ๋กœ ์ „๋‹ฌ์ด ๋˜์—ˆ์—ˆ๊ณ , ์ต๋ช… ํ•จ์ˆ˜(๋žŒ๋‹ค)๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘์„ฑ๋˜์—ˆ๋Š”์ง€ ๊ธฐ์–ตํ•˜์ž.
  • ์ž๋ฐ” 8์—์„œ ์ŠคํŠธ๋ฆผ์€ ์ปฌ๋ ‰์…˜์˜ ๋งŽ์€ ๋ฉด๋ชจ๋ฅผ ์ผ๋ฐ˜ํ™”ํ•˜์˜€๋‹ค. ์ผ๋ฐ˜ํ™”ํ•˜์˜€์ง€๋งŒ, ์ŠคํŠธ๋ฆผ์€ ๋” ์ฝ๊ธฐ ์‰ฌ์šด ์ฝ”๋“œ๋ฅผ ์ œ๊ณตํ•˜๊ณ  ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋“ค์ด ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌ๋˜๊ฒŒ ํ•ด์ค€๋‹ค.
  • ์ž๋ฐ”๋Š”, ํฐ ์ปดํฌ๋„ŒํŠธ ๊ธฐ๋ฐ˜์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด๋‚˜ ๋ฐœ์ „ํ•˜๋Š” ์‹œ์Šคํ…œ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ž˜ ๋‹ค๋ฃจ์ง€ ๋ชปํ•˜์˜€๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ง€๊ธˆ์€ ์ž๋ฐ”9์—์„œ ์‹œ์Šคํ…œ์„ ๊ตฌ์กฐํ™”ํ•˜๊ธฐ ์œ„ํ•ด ๋ชจ๋“ˆ์„ ๋ช…์‹œํ•  ์ˆ˜ ์žˆ๊ณ , ๋ชจ๋“  ๊ตฌํ˜„๋ถ€ ํด๋ž˜์Šค๋“ค์˜ ์ˆ˜์ •์—†์ด ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ถ”๊ฐ€ํ•จ ์œผ๋กœ์จ ์†์‰ฝ๊ฒŒ๋ณ€๊ฒฝ์ด ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋˜์—ˆ๋‹ค.
  • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ ๋ถ€ํ„ฐ ์˜จ ๊ฐœ๋…๋“ค์ด ๋„๊ณผ ํŒจํ„ด๋งค์นญ์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ์—ˆ๋‹ค.
โš ๏ธ **GitHub.com Fallback** โš ๏ธ