Giter VIP home page Giter VIP logo

modern-java-in-action-study's Introduction

Anurag's GitHub stats

Tech Blog Badge Notion Badge Notion Badge Gmail Badge

๐Ÿ’โ€โ™‚๏ธ About me

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

โš’ Skills

๐Ÿ“š Education
์šฐ์•„ํ•œํ…Œํฌ์ฝ”์Šค 2021.02 - 2021.11
์•„์ฃผ๋Œ€ํ•™๊ต 2015.03 - 2021.02

modern-java-in-action-study's People

Watchers

 avatar

modern-java-in-action-study's Issues

Chapter 6. ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘

์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘

์šฐ๋ฆฌ๋Š” ์ด ์žฅ์—์„œ reduce์ฒ˜๋Ÿผ collect๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋‹ค์–‘ํ•œ ์š”์†Œ ๋ˆ„์  ๋ฐฉ์‹์„ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์†Œ๊ฐœํ•  ๊ฒƒ์ด๋‹ค. ๋‹ค์–‘ํ•œ ์š”์†Œ ๋ˆ„์  ๋ฐฉ์‹์€ Collector ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋˜์–ด ์žˆ๋Š”๋ฐ ์ปฌ๋ ‰์…˜, ์ปฌ๋ ‰ํ„ฐ collect๋ฅผ ํ—ท๊ฐˆ๋ฆฌ์ง€ ์•Š๋„๋ก ๋”ฐ๋ผ์™€์•ผํ•œ๋‹ค.

๋จผ์ € ํ•˜๋‚˜ ์˜ˆ์‹œ๋ฅผ ๋“ค๊ฒ ๋‹ค.

  1. ํ†ตํ™”๋ณ„๋กœ ํŠธ๋ž™์žญ์…˜์„ ๊ทธ๋ฃนํ™”ํ•œ ๋‹ค์Œ ํ•ด๋‹น ํ†ตํ™”๋กœ ์ผ์–ด๋‚œ ๋ชจ๋“  ํŠธ๋ž™์žญ์…˜ ํ•ฉ๊ณ„๋ฅผ ๊ณ„์‚ฐ
  2. ํŠธ๋žœ์žญ์…˜์„ ๋น„์‹ผ ํŠธ๋žœ์žญ์…˜๊ณผ ์ €๋ ดํ•œ ํŠธ๋žœ์žญ์…˜ ๋‘ ๊ทธ๋ฃน์œผ๋กœ ๋ถ„๋ฅ˜
  3. ํŠธ๋žœ์žญ์…˜์„ ๋„์‹œ ๋“ฑ ๋‹ค์ˆ˜์ค€์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•˜์‹œ์˜ค. ๊ทธ๋ฆฌ๊ณ  ๊ฐ ํŠธ๋žœ์žญ์…˜์ด ๋น„์‹ผ์ง€ ์ €๋ ดํ•œ์ง€ ๊ตฌ๋ถ„ํ•˜์‹œ์˜ค

๋‹ค์Œ์€ ์ž๋ฐ” 8 ์ด์ „ ์ฝ”๋“œ๋กœ ์ž‘์„ฑํ•œ ์ฝ”๋“œ์ด๋‹ค.

Map<Currency, List<Transcation>> transactionsByCurrencies = new HashMap<>();

        for (Transaction transaction : transactions) {
            Currency currency = transaction.getCurrency();
            List<Transcation> transactionsForCurrency = transactionsByCurrencies.get(currency);
            if(transactionsForCurrency == null){
                transactionsForCurrency = new ArrayList<>();
                transactionsByCurrencies.put(currency, transactionsForCurrency);
            }
            transactionsForCurrency.add(transaction);
        }

ํŠธ๋žœ์žญ์…˜์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜๋ณตํ•˜์—ฌ ๋ถ€๋ฅธ ํ›„ ๊ฐ™์€ ํ†ตํ™”๋ฅผ ๊ฐ€์ง„ ํŠธ๋žœ์žญ์…˜ ๋ฆฌ์ŠคํŠธ์— ํ˜„์žฌ ํƒ์ƒ‰ ์ค‘์ธ ํŠธ๋žœ์žญ์…˜์„ ์ถ”๊ฐ€ํ•œ๋‹ค.
๋งŒ์•ฝ ํ˜„์žฌ ๊ฐ™์€ ํ†ตํ™”๊ฐ€ ์—†์œผ๋ฉด ์ƒˆ๋กœ์šด ํ•ญ๋ชฉ์„ ๋งŒ๋“ ๋‹ค.

์œ„์˜ ์ฝ”๋“œ๋Š” ํ•œ๋ˆˆ์— ์•Œ์•„๋ณด๊ธฐ๋„ ์–ด๋ ต๊ณ  ๊ตฌํ˜„ํ•˜๊ธฐ๋„ ์–ด๋ ต๋‹ค. ์ด๋ฅผ collect ๋ฉ”์„œ๋“œ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” ์—ฐ์‚ฐ์„ ๋”์šฑ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

Map<Currency, List<Transaction>> transactionsByCurrencies =
 transactions.stream().collect(groupingBy(Transaction::getCurrency));

์•ž์„  ์ฝ”๋“œ์™€ ๋น„๊ตํ–ˆ์„ ๋•Œ ํ•œ๋ˆˆ์— ์•Œ์•„๋ณด๊ธฐ๋„ ์‰ฝ๊ณ  ์ฝ”๋“œ ๋˜ํ•œ ์งง์•„ ์กŒ๋‹ค.

์ปฌ๋ ‰ํ„ฐ๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

์•ž์„  ์˜ˆ์ œ๋ฅผ ๋ณด๋ฉด ๋ช…๋ นํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์— ๋น„ํ•ด ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ์–ผ๋งˆ๋‚˜ ํŽธ๋ฆฌํ•œ์ง€ ๋ช…ํ™•ํ•˜๊ฒŒ ๋ณด์—ฌ์ฃผ๊ณ  ์žˆ๋‹ค.
์˜ˆ์ œ์—์„œ collect ๋ฉ”์„œ๋“œ๋กœ Collector ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์„ ์ „๋‹ฌํ–ˆ๋‹ค. Collector ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„์€ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋ฅผ ์–ด๋–ค ์‹์œผ๋กœ ๋„์ถœํ• ์ง€ ์ง€์ •ํ•œ๋‹ค. ์ด๋ฒˆ์— ๋ณผ ๋ฉ”์„œ๋“œ๋Š” groupingBy ๋ฉ”์„œ๋“œ๋กœ ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ, ๊ฐ ํ‚ค์™€ ๊ฐ ํ‚ค์— ๋Œ€์‘ํ•˜๋Š” ์š”์†Œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ’์œผ๋กœ ํฌํ•จํ•˜์—ฌ ๋งต์„ ๋งŒ๋“ค์–ด ๋‚ผ ๊ฒƒ์ด๋‹ค.

๋ฏธ๋ฆฌ ์ •์˜๋œ ์ปฌ๋ ‰ํ„ฐ

์ปฌ๋ ‰ํ„ฐ์—์„œ ๋ฏธ๋ฆฌ ์ •์˜๋œ groupingBy์™€ ๊ฐ™์€ Collectors ํด๋ž˜์Šค์—์„œ ์ œ๊ณตํ•˜๋Š” ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋Šฅ์„ ์‚ดํŽด๋ณผ ๊ฒƒ์ด๋‹ค.
Collectors์—์„œ ์ œ๊ณตํ•˜๋Š” ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋Šฅ์€ ํฌ๊ฒŒ ์„ธ ๊ฐ€์ง€๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ŠคํŠธ๋ฆผ ์š”์†Œ๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ๋ฆฌ๋“€์Šคํ•˜๊ณ  ์š”์•ฝ
  • ์š”์†Œ ๊ทธ๋ฃนํ™”
  • ์š”์†Œ ๋ถ„ํ• 

๋ฆฌ๋“€์‹ฑ๊ณผ ์š”์•ฝ

5์žฅ์—์„œ ๋‹ค๋ฃฌ ์š”๋ฆฌ ์˜ˆ์ œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์‚ดํŽด๋ณด๊ฒ ๋‹ค.

์ฒซ ๋ฒˆ์งธ ์˜ˆ๋กœ counting()์ด๋ผ๋Š” ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ปฌ๋ ‰ํ„ฐ๋กœ ๋ฉ”๋‰ด์—์„œ ์š”๋ฆฌ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•ด์ค€๋‹ค.

long howManyDishs = menu.stream().collect(Collectors.counting());
->
long howManyDishs = menu.stream().count();

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋ถˆํ•„์š”ํ•œ ๊ณผ์ •์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๋‹ค.
Collectors ํด๋ž˜์Šค๋ฅผ ์ž„ํฌํŠธ๋ฅผ ํ•˜๊ฒŒ๋˜๋ฉด ์•ž์„  ์˜ˆ์ œ์ฒ˜๋Ÿผ Collectors.counting()์„ ๊ฐ„๋‹จํ•˜๊ฒŒ counting()์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ŠคํŠธ๋ฆผ ๊ฐ’์—์„œ ์ตœ๋Œ“๊ฐ’ ์ตœ์†Œ๊ฐ’ ๊ฒ€์ƒ‰

๋งŒ์•ฝ ๋ฉ”๋‰ด์—์„œ ์นผ๋กœ๋ฆฌ๊ฐ€ ๊ฐ€์žฅ ๋†’์€ ์š”๋ฆฌ๋ฅผ ์ฐพ๋Š”๋‹ค๊ณ  ๊ฐ€์ •ํ•˜์ž. Collectors์— ์ •์˜๋˜์–ด ์žˆ๋Š” maxBy(), minBy()๋ฅผ ์ด์šฉํ•˜์—ฌ ์ตœ๋Œ“๊ฐ’ ์ตœ์†Œ๊ฐ’์„ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

Comparator<Dish> dishCaloriesComparator = Comparator.comparingInt(Dish::getCalories);

Optional<Dish> mostCalorieDish = menu.stream().collect(maxBy(dishCaloriesComparator));

์š”์•ฝ ์—ฐ์‚ฐ

Collectors ํด๋ž˜์Šค๋Š” ์ŠคํŠธ๋ฆผ์— ์žˆ๋Š” ๊ฐ์ฒด์˜ ์ˆซ์ž ํ•„๋“œ์˜ ํ•ฉ๊ณ„๋‚˜ ํ‰๊ท  ๋“ฑ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ฐ์‚ฐ ๋˜ํ•œ ์ง€์›ํ•œ๋‹ค.
summingInt, averagingInt ๋“ฑ ํ•ฉ, ํ‰๊ท ๊ฐ’ ๊ณ„์‚ฐ ๋“ฑ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์—ฐ์‚ฐ์ด ์ง€์›๋œ๋‹ค.

int totalCalories = menu.stream().collect(summingInt(Dish::getCalories));

์œ„์˜ ์ฝ”๋“œ๋Š” ๋ฉ”๋‰ด ๋ฆฌ์ŠคํŠธ์˜ ํ•ฉ๊ณ„๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค. ์ด์ฒ˜๋Ÿผ Collectors ๋˜ํ•œ ์ŠคํŠธ๋ฆผ์˜ ๋ฆฌ๋“€์‹ฑ์ฒ˜๋Ÿผ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์—ฐ์‚ฐ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋Ÿฌํ•œ ๋‹จ์ˆœ ํ•ฉ๊ณ„์™ธ์— ์š”์†Œ ์ˆ˜, ์ตœ๋Œ“๊ฐ’ ์ตœ์†Œ๊ฐ’, ํ•ฉ๊ณ„์™€ ํ‰๊ท ์„ ํ•œ๊บผ๋ฒˆ์— ๊ณ„์‚ฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•ด์ฃผ๋Š” summarizingInt ๋˜ํ•œ ์ง€์›ํ•ด์ค€๋‹ค.

IntSummaryStatistics menuStatistics = menu.stream().collect(summarizingInt(Dish::getCalories));

์œ„์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด IntSummaryStatistics๋กœ ๋ชจ๋“  ์ •๋ณด๊ฐ€ ์ˆ˜์ง‘๋œ๋‹ค. menuStaticstics ๊ฐ์ฒด๋ฅผ ์ถœ๋ ฅํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ •๋ณด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

IntSummaryStatistics { count = 9, sum=4300, min=120, average=477.777778, max=800}

์•ž์—์„œ๋Š” int๋งŒ ์„ค๋ช…ํ–ˆ์ง€๋งŒ ์ด์™€ ๋น„์Šทํ•œ Double, Long์— ๋Œ€ํ•œ ํด๋ž˜์Šค๋„ ์žˆ๋‹ค.

๋ฌธ์ž์—ด ์—ฐ๊ฒฐ

์ปฌ๋ ‰ํ„ฐ๋Š” ์ŠคํŠธ๋ฆผ์˜ ๊ฐ ๊ฐ์ฒด๋ฅผ ์—ฐ๊ฒฐํ•˜์—ฌ ํ•˜๋‚˜์˜ ๋ฌธ์ž์—ด๋กœ ์—ฐ๊ฒฐํ•˜๋Š” joining ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค.

String shortMenu = menu.stream().map(Dish::getName).collect(joining(", "));

์œ„์˜ ์ฝ”๋“œ๋Š” ๊ฐ ๊ฐ์ฒด๋ฅผ , ๋กœ ์—ฐ๊ฒฐํ•ด์ฃผ๋Š” ์ฝ”๋“œ์ด๋‹ค.

๋ฒ”์šฉ ๋ฆฌ๋“€์‹ฑ ์š”์•ฝ ์—ฐ์‚ฐ

์ง€๊ธˆ๊นŒ์ง€ ์‚ดํŽด๋ณธ ๋ชจ๋“  ์ปฌ๋ ‰ํ„ฐ๋Š” reducing ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ๋กœ๋„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ๋ฒ”์šฉ Collectors.reducing์œผ๋กœ๋„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

int totalCalories = menu.stream().collect(reducing(0, Dish::getCalories, (i, j) -> i + j));

์œ„์˜ ์ฝ”๋“œ๋Š” reducing ๋ฉ”์„œ๋“œ๋กœ ๋งŒ๋“ค์–ด์ง„ ์ปฌ๋ ‰ํ„ฐ๋กœ ๋ฉ”๋‰ด์˜ ๋ชจ๋“  ์นผ๋กœ๋ฆฌ ํ•ฉ๊ณ„๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.
reducing์€ ์ธ์ˆ˜ ์„ธ ๊ฐœ๋ฅผ ๋ฐ›๋Š”๋‹ค.

  1. ์ฒซ ๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ๋ฆฌ๋“€์‹ฑ ์—ฐ์‚ฐ์˜ ์‹œ์ž‘๊ฐ’์ด๊ฑฐ๋‚˜ ์ŠคํŠธ๋ฆผ์— ์ธ์ˆ˜๊ฐ€ ์—†์„ ๋•Œ๋Š” ๋ฐ˜ํ™˜๊ฐ’์ด๋‹ค.
  2. ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ์š”๋ฆฌ๋ฅผ ์นผ๋กœ๋ฆฌ ์ •์ˆ˜๋กœ ๋ณ€ํ™˜ํ•  ๋•Œ ์‚ฌ์šฉํ•œ ๋ณ€ํ™˜ ํ•จ์ˆ˜๋‹ค.
  3. ์„ธ ๋ฒˆ์งธ ์ธ์ˆ˜๋Š” ๊ฐ™์€ ์ข…๋ฅ˜์˜ ๋‘ ํ•ญ๋ชฉ์„ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ๋”ํ•˜๋Š” BinaryOperator๋‹ค. ์˜ˆ์ œ์—์„œ๋Š” ๋‘ ๊ฐœ์˜ int๊ฐ€ ์‚ฌ์šฉ๋˜์—ˆ๋‹ค.

๊ทธ๋ฃนํ™”

๋งจ ์ฒ˜์Œ ๋ณด์•˜๋˜ ํ†ตํ™” ๊ทธ๋ฃนํ™” ์˜ˆ์ œ์—์„œ ํ™•์ธ ํ–ˆ๋“ฏ์ด ๋ช…๋ นํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์œผ๋กœ ๊ทธ๋ฃนํ™”๋ฅผ ๊ตฌํ˜„ํ•˜๋ ค๋ฉด ๊นŒ๋‹ค๋กญ๊ณ , ํ• ์ผ์ด ๋งŽ์œผ๋ฉฐ, ์—๋Ÿฌ๋„ ๋งŽ์ด ๋ฐœ์ƒํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ž๋ฐ” 8์˜ ํ•จ์ˆ˜ํ˜•์„ ์ด์šฉํ•˜๋ฉด ๊ฐ€๋…์„ฑ ์žˆ๋Š” ํ•œ ์ค„์˜ ์ฝ”๋“œ๋กœ ๊ทธ๋ฃนํ™”๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฒˆ ์ฝ”๋“œ๋Š” ์š”๋ฆฌ๋ฅผ ๊ณ ๊ธฐ, ์ƒ์„ , ๋‚˜๋จธ์ง€ ๊ทธ๋ฃน์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

Map<Dish.Type, List<Dish>> dishesByType = menu.stream().collect(groupingBy(Dish::getType));
// result
{FISH =[prawns, salmon], OTHER={french fries, rice, season fruit, pizza], MEAT=[pork, beef, chicken]}

์ด์ฒ˜๋Ÿผ groupingBy๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” ๊ทธ๋ฃน์œผ๋กœ ๋ถ„๋ฅ˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋ฅผ ๋ถ„๋ฅ˜ ํ•จ์ˆ˜๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

์œ„์ฒ˜๋Ÿผ ๋‹จ์ˆœ ์†์„ฑ ์ ‘๊ทผ์ž ๋Œ€์‹  ๋” ๋ณต์žกํ•œ ๋ถ„๋ฅ˜ ๊ธฐ์ค€์ด ํ•„์š”ํ•œ ์ƒํ™ฉ์—์„œ๋Š” ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
๋‹ค์Œ์€ 400 ์นผ๋กœ๋ฆฌ ์ดํ•˜๋ฅผ diet๋กœ 400~ 700์นผ๋กœ๋ฆฌ๋ฅผ normal๋กœ, 700 ์นผ๋กœ๋ฆฌ ์ดˆ๊ณผ๋ฅผ fat ์š”๋ฆฌ๋กœ ๋ถ„๋ฅ˜ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•œ๋‹ค.
์ด ๋ถ„๋ฅ˜ ๊ธฐ์ค€์„ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋Œ€์‹  ๋žŒ๋‹ค ํ‘œํ˜„์‹์œผ๋กœ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

public enumCaloricLevel { DIET, NORMAL, FAT}

        Map<CaloricLevel, List<Dish>> dishesByCaloricLevel = menu.stream().collect(groupingBy(dish->{
            if(dish.getCalories() <= 400) return CaloricLevel.DIET;
            else if(dish.getCalories() <= 700) return CaloricLevel.NORMAL;
            else return CaloricLevel.FAT;
        }));

๊ทธ๋ฃนํ™”๋œ ์š”์†Œ ์กฐ์ž‘

์•ž์„  ์˜ˆ์ œ๋ฅผ ํ†ตํ•ด groupBy ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•œ ๊ฐ€์ง€ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด์•˜๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด 2๊ฐ€์ง€ ์ด์ƒ์˜ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

์šฐ์„  ์ŠคํŠธ๋ฆผ์˜ filter ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

Map<Dish.Type, List<Dish>> caloricDishesByType = 
                menu.stream().filter(dish -> dish.getCalories() > 500)
                             .collect(groupingBy(Dish::getType));

์œ„ ์ฝ”๋“œ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋‹จ์ ์ด ์กด์žฌํ•œ๋‹ค.
{ OTHER=[french fries, pizza], MEAT=[pork, beef]}
๋ฌธ์ œ๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๋ฐœ๊ฒฌํ–ˆ๋Š”๊ฐ€? FISH๋Š” filter๋ฅผ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๊ฐ€ ์—†์œผ๋ฏ€๋กœ FISH ํ•ญ๋ชฉ์ด ์•„์˜ˆ ๋น ์ ธ์žˆ๋‹ค.
์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด Collectors ํด๋ž˜์Šค๋Š” groupingBy ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋ฅผ ๊ฐ–๋Š” ์˜ค๋ฒ„๋กœ๋”ฉ์„ ์‚ฌ์šฉํ•œ๋‹ค.

Map<Dish.Type, List<Dish>> caloricDishesByType =
        menu.stream()
            .collect(groupingBy(Dish::getType,
                    filtering(dish -> dish.getCalories() > 500, toList())));

// result
{OTHER=[french fries, pizza], MEAT=[pork, beef], FISH=[]}

๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด ์•Œ์ˆ˜ ์žˆ๋“ฏ์ด ๋ชฉ๋ก์ด ๋น„์–ด์žˆ๋Š” FISH๋„ ํ•ญ๋ชฉ์œผ๋กœ ์ถ”๊ฐ€๋œ๋‹ค.

๋‹ค์ˆ˜์ค€ ๊ทธ๋ฃนํ™”

๋‘ ์ธ์ˆ˜๋ฅผ ๋ฐ›๋Š” ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ Collectors.groupingBy๋ฅผ ์ด์šฉํ•ด์„œ ํ•ญ๋ชฉ์„ ๋‹ค์ˆ˜์ค€์œผ๋กœ ๊ทธ๋ฃนํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค. Collectors.groupingBy๋Š” ์ผ๋ฐ˜์ ์ธ ๋ถ„๋ฅ˜ ํ•จ์ˆ˜์™€ ์ปฌ๋ ‰ํ„ฐ๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š”๋‹ค. ์ฆ‰, ๋‘ ๊ฐ€์ง€ ๊ธฐ์ค€์œผ๋กœ ํ•ญ๋ชฉ์„ ๊ทธ๋ฃนํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.

Map<Dish.Type, Map<CaloricLevel, List<Dish>>> dishesByTypeCaloricLevel =
                menu.stream().collect(
                        groupingBy(Dish::getType,
                                groupingBy(dish -> {
                                    if(dish.getCalories() <= 400)
                                        return CaloricLevel.DIET;
                                    else if(dish.getCalories() <= 700)
                                        return CaloricLevel.NORMAL;
                                    else
                                        return CaloricLevel.FAT;
                                })
                        })
                );

๊ทธ๋ฃนํ™” ๊ฒฐ๊ณผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋‘ ์ˆ˜์ค€์˜ ๋งต์ด ๋งŒ๋“ค์–ด ์ง„๋‹ค.

{MEAT={DIET=[chicken], NORMAL=[beef], FAT=[pork]}, FISH={DIET=[prawns], NORMAL=[salmon]},
OTHER={DIET=[rice, sasonal fruit], NORMAL=[french fries, pizza]}}

์ฒซ ๋ฒˆ์งธ ๋ถ„๋ฅ˜ ํ•จ์ˆ˜์—์„œ๋Š” fish, meat, other๋ฅผ ๊ธฐ์ค€์œผ๋กœ, ๋‘ ๋ฒˆ์งธ๋Š” normal, diet, fat์„ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃนํ™” ๋œ๋‹ค.

์„œ๋ธŒ๊ทธ๋ฃน์œผ๋กœ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘

groupingBy ์ปฌ๋ ‰ํ„ฐ์— ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ counting ์ปฌ๋ ‰ํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์„œ ๋ฉ”๋‰ด์—์„œ ์š”๋ฆฌ ์ˆ˜๋ฅผ ์ข…๋ฅ˜๋ณ„๋กœ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.

Map<Dish.Type, Long> typesCount = menu.stream().collect(groupingBy(Dish::getType, counting()));
// result
{MEAT=3, FISH=2, OTHER=4}

๋ถ„๋ฅ˜ ํ•จ์ˆ˜ ํ•œ ๊ฐœ์˜ ์ธ์ˆ˜๋ฅผ ๊ฐ–๋Š” groupingBy(f)๋Š” ์‚ฌ์‹ค groupingBy(f, toList())์˜ ์ถ•์•ฝํ˜•์ด๋‹ค.

์ปฌ๋ ‰ํ„ฐ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค๋ฅธ ํ˜•์‹์— ์ ์šฉํ•˜๊ธฐ

๋งˆ์ง€๋ง‰ ๊ทธ๋ฃนํ™” ์—ฐ์‚ฐ์—์„œ ๋งต์˜ ๋ชจ๋“  ๊ฐ’์„ Optional๋กœ ๊ฐ์Œ€ ํ•„์š”๊ฐ€ ์—†์œผ๋ฏ€๋กœ Optional์„ ์‚ญ์ œํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ๋‹ค์Œ์ฒ˜๋Ÿผ ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ Collectros.collectingAndThen์œผ๋กœ ์ปฌ๋ ‰ํ„ฐ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋‹ค๋ฅธ ํ˜•์‹์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Map<Dish.Type, Dish> mostCaloricByType =
                menu.stream()
                    .collect(groupingBy(Dish::getType,
                            collectingAndThen(
                                    maxBy(comparingInt(Dish::getCalories)), 
                            Optional::get)));

ํŒฉํ† ๋ฆฌ ๋ฉ”์„œ๋“œ collectingAndThen์€ ์ ์šฉํ•  ์ปฌ๋ ‰ํ„ฐ์™€ ๋ณ€ํ™˜ ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ๋‹ค๋ฅธ ์ปฌ๋ ‰ํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

๋ถ„ํ• 

๋ถ„ํ• ์€ ๋ถ„ํ•  ํ•จ์ˆ˜๋ผ ๋ถˆ๋ฆฌ๋Š” ํ”„๋ ˆ๋”” ์ผ€์ดํŠธ๋ฅผ ๋ถ„๋ฅ˜ ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉํ•˜๋Š” ํŠน์ˆ˜ํ•œ ๊ทธ๋ฃนํ™” ๊ธฐ๋Šฅ์ด๋‹ค. ๋ถ„ํ•  ํ•จ์ˆ˜๋Š” ๋ถˆ๋ฆฌ์–ธ์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ๋งต์˜ ํ‚ค ํ˜•์‹์€ Boolean์ด๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ๊ทธ๋ฃนํ™” ๋งต์€ ์ตœ๋Œ€ (true or false) ๋‘ ๊ฐœ์˜ ๊ทธ๋ฃน์œผ๋กœ ๋ถ„๋ฅ˜๋œ๋‹ค.
์˜ˆ๋ฅผ ๋“ค์–ด ์ฑ„์‹์ธ ์š”๋ฆฌ์™€ ์•„๋‹Œ ์š”๋ฆฌ๋กœ ๊ตฌ๋ถ„ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด๋œ๋‹ค.

Map<Boolean, List<Dish>> partitioneMenu = menu.stream().collect(partitioningBy(Dish::isVegetarina));
// result
{false=[pork, beef, chicken, prawns, salmon],
true=[french fries, rice, season fruit, pizza]}

์ด์ œ ์ฐธ๊ฐ’์˜ ํ‚ค๋กœ ๋งต์—์„œ ๋ชจ๋“  ์ฑ„์‹ ์š”๋ฆฌ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

List<Dish> vegetarianDishes = partitionedMenu.get(true);

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

์ด๋ฒˆ ์žฅ์—์„œ๋Š” Collector ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด์„œ ๋” ํšจ์œจ์ ์œผ๋กœ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ์ปฌ๋ ‰ํ„ฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณธ๋‹ค.

public interface Collector<T, A, R> {
            Supplier<A> supplier();
            BiConsumer<A, T> accumulator();
            Function<A, R> finisher();
            BinaryOperator<A> combiner();
            Set<Characteristics> characteristics();
        }

์œ„์˜ ์ฝ”๋“œ๋Š” Collector ์ธํ„ฐํŽ˜์ด์Šค์˜ ์‹œ๊ทธ๋‹ˆ์ฒ˜์™€ ๋‹ค์„ฏ ๊ฐœ์˜ ๋ฉ”์„œ๋“œ ์ •์˜๋ฅผ ๋ณด์—ฌ์ค€๋‹ค. ์ด๊ฒƒ์€ ๋‹ค์Œ์ฒ˜๋Ÿผ ์„ค๋ช…ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • T๋Š” ์ˆ˜์ง‘๋  ์ŠคํŠธ๋ฆผ ํ•ญ๋ชฉ์˜ ์ œ๋„ค๋ฆญ ํ˜•์‹์ด๋‹ค.
  • A๋Š” ๋ˆ„์ ์ž, ์ฆ‰ ์ˆ˜์ง‘ ๊ณผ์ •์—์„œ ์ค‘๊ฐ„ ๊ฒฐ๊ณผ๋ฅผ ๋ˆ„์ ํ•˜๋Š” ๊ฐ์ฒด์˜ ํ˜•์‹์ด๋‹ค.
  • R์€ ์ˆ˜์ง‘ ์—ฐ์‚ฐ ๊ฒฐ๊ณผ ๊ฐ์ฒด์˜ ํ˜•์‹(ํ•ญ์ƒ ๊ทธ๋Ÿฐ ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ๋Œ€๊ฐœ ์ปฌ๋ ‰์…˜ ํ˜•์‹)์ด๋‹ค.

์ด Collector ์ธํ„ฐํŽ˜์ด์Šค์˜ 5๊ฐ€์ง€ ๋ฉ”์„œ๋“œ๋ฅผ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด์ž. ๋จผ์ € ์‚ดํŽด๋ณผ ๋„ค ๊ฐœ์˜ ๋ฉ”์„œ๋“œ๋Š” collect ๋ฉ”์„œ๋“œ์—์„œ ์‹คํ–‰ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐ˜๋ฉด, ๋‹ค์„ฏ ๋ฒˆ์งธ ๋ฉ”์„œ๋“œ characteristics๋Š” collect ๋ฉ”์„œ๋“œ๊ฐ€ ์–ด๋–ค ์ตœ์ ํ™”๋ฅผ ์ด์šฉํ•ด์„œ ๋ฆฌ๋“€์‹ฑ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•  ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•˜๋„๋ก ๋•๋Š” ํžŒํŠธ ํŠน์„ฑ ์ง‘ํ•ฉ์„ ์ œ๊ณตํ•œ๋‹ค.

  • supplier ๋ฉ”์„œ๋“œ : ์ƒˆ๋กœ์šด ๊ฒฐ๊ณผ ์ปจํ…Œ์ด๋„ˆ ๋งŒ๋“ค๊ธฐ
  • accumulator ๋ฉ”์„œ๋“œ : ๊ฒฐ๊ณผ ์ปจํ…Œ์ด๋„ˆ์— ์š”์†Œ ์ถ”๊ฐ€ํ•˜๊ธฐ
  • finisher ๋ฉ”์„œ๋“œ : ์ตœ์ข… ๋ณ€ํ™˜๊ฐ’์„ ๊ฒฐ๊ณผ ์ปจํ…Œ์ด๋„ˆ๋กœ ์ ์šฉํ•˜๊ธฐ
  • combiner ๋ฉ”์„œ๋“œ : ๋‘ ๊ฒฐ๊ณผ ์ปจํ…Œ์ด๋„ˆ ๋ณ‘ํ•ฉ
  • Characteristics ๋ฉ”์„œ๋“œ : ์ปฌ๋ ‰ํ„ฐ์˜ ์—ฐ์‚ฐ์„ ์ •์˜ํ•˜๋Š” Characteristics ํ˜•์‹์˜ ๋ถˆ๋ณ€ ์ง‘ํ•ฉ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ์ปค์Šคํ…€ ์ปฌ๋ ‰ํ„ฐ๋ฅผ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.

๋งˆ์น˜๋ฉฐ

  • collect๋Š” ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋ฅผ ์š”์•ฝ ๊ฒฐ๊ณผ๋กœ ๋ˆ„์ ํ•˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐฉ๋ฒ•(์ปฌ๋ ‰ํ„ฐ๋ผ ๋ถˆ๋ฆฌ๋Š”)์„ ์ธ์ˆ˜๋กœ ๊ฐ–๋Š” ์ตœ์ข… ์—ฐ์‚ฐ์ด๋‹ค.
  • ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ๋ฆฌ๋“€์Šคํ•˜๊ณ  ์š”์•ฝํ•˜๋Š” ์ปฌ๋ ‰ํ„ฐ๋ฟ ์•„๋‹ˆ๋ผ ์ตœ์†Ÿ๊ฐ’, ์ตœ๋Œ€๊ฐ’, ํ‰๊ท ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋Š” ์ปฌ๋ ‰ํ„ฐ ๋“ฑ์ด ๋ฏธ๋ฆฌ ์ •์˜๋˜์–ด ์žˆ๋‹ค.
  • ๋ฏธ๋ฆฌ ์ •์˜๋œ ์ปฌ๋ ‰ํ„ฐ์ธ groupingBy๋กœ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๊ฑฐ๋‚˜, partitioningBy๋กœ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋ฅผ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ปฌ๋ ‰ํ„ฐ๋Š” ๋‹ค์ˆ˜์ค€์˜ ๊ทธ๋ฃนํ™”, ๋ถ„ํ• , ๋ฆฌ๋“€์‹ฑ ์—ฐ์‚ฐ์— ์ ํ•ฉํ•˜๊ฒŒ ์„ค๊ณ„๋˜์–ด ์žˆ๋‹ค.
  • Collector ์ธํ„ฐํŽ˜์ด์Šค์— ์ •์˜๋œ ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์„œ ์ปค์Šคํ…€ ์ปฌ๋ ‰ํ„ฐ๋ฅผ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋‹ค.

Chapter 3. ๋žŒ๋‹ค ํ‘œํ˜„์‹

๋žŒ๋‹ค ํ‘œํ˜„์‹

๋žŒ๋‹ค๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ๋ฉ”์„œ๋“œ๋กœ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ์ต๋ช… ํ•จ์ˆ˜๋ฅผ ๋‹จ์ˆœํ™”ํ•œ ๊ฒƒ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋žŒ๋‹ค ํŠน์ง•

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

๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ์•ž์„œ 2์žฅ์—์„œ ๋ณธ ์ž์งˆ๊ตฌ๋ ˆํ•œ ์ฝ”๋“œ๋“ค์„ ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ค„์ผ ์ˆ˜ ์žˆ๋‹ค.

Comparator<Apple> byWeight = new Comparator<Apple>(){
            public int compare(Apple a1, Apple a2) {
                return a1.getWeight().compareTo(a2.getWeight());
            }
        };
Comparator<Apple> byWeight = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

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

๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ์•„๋ž˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ํ™”์‚ดํ‘œ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐ, ํ™”์‚ดํ‘œ, ๋ฐ”๋””๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค.

(Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight());

๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ์–ด๋””์— ์‚ฌ์šฉํ•˜๋Š”๊ฐ€?

List<Apple> greenApples = filter(inventory, (Apple a) -> GREEN.equals(a.getColor()));

๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ๋ฐฐ์› ์œผ๋‹ˆ ์šฐ๋ฆฌ๋Š” ์ด๋ฅผ ์จ๋จน์–ด์•ผํ•œ๋‹ค. ๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ์–ด๋””์—, ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๊ฐ€? ์•ž์„œ ๊ณต๋ถ€ํ•œ 2์žฅ์—์„œ ๊ตฌํ˜„ํ–ˆ๋˜ ํ•„ํ„ฐ ๋ฉ”์„œ๋“œ์—๋„ ๋žŒ๋‹ค๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. ๋˜ํ•œ ์ด์ œ ์†Œ๊ฐœํ•  ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ผ๋Š” ๋ฌธ๋งฅ์—์„œ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์œ„์˜ ์˜ˆ์ œ์—์„œ๋Š” ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค Predicate๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š” filter ๋ฉ”์„œ๋“œ์˜ ๋‘ ๋ฒˆ์งธ ์ธ์ˆ˜๋กœ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์ „๋‹ฌํ•œ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ทธ๋ ‡๋‹ค๋ฉด ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋ฌด์—‡์ผ๊นŒ?

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

        public interface Predicate<T> {
            boolean test (T t);
        }

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

๋žŒ๋‹ค ํ™œ์šฉ : ์‹คํ–‰ ์–ด๋ผ์šด๋“œ ํŒจํ„ด

์ž์› ์ฒ˜๋ฆฌ์— ์‚ฌ์šฉํ•˜๋Š” ์ˆœํ™˜ ํŒจํ„ด์€ ์ž์›์„ ์—ด๊ณ , ์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ, ์ž์›์„ ๋‹ซ๋Š” ์ˆœ์„œ๋กœ ์ด๋ฃจ์–ด์ง„๋‹ค. ์„ค์ •๊ณผ ์ •๋ฆฌ ๊ณผ์ •์€ ๋Œ€๋ถ€๋ถ„ ๋น„์Šทํ•˜๋‹ค. ์ฆ‰, ์‹ค์ œ ์ž์›์„ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์„ค์ •๊ณผ ์ •๋ฆฌ ๋‘ ๊ณผ์ •์ด ๋‘˜๋Ÿฌ์‹ธ๋Š” ํ˜•ํƒœ๋ฅผ ๊ฐ–๋Š”๋‹ค. ์ด๋Ÿฌํ•œ ๊ฒƒ์„ ์‹คํ–‰ ์–ด๋ผ์šด๋“œ ํŒจํ„ด์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

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

์ž๋ฐ” 8 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค๊ณ„์ž๋“ค์€ java.util.function ํŒจํ‚ค์ง€๋กœ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค ํ•จ์ˆ˜ ๋””์Šคํฌ๋ฆฝํ„ฐ ๊ธฐ๋ณธํ˜• ํŠนํ™”
Predicate T->boolean IntPredicate, LongPredicate, DoublePredicate
Consumer T->void IntConsumer, LongConsumer, DoubleConsumer
function<T, R> T->R IntFunction, IntToDoubleFunction, IntToLongFunction...

ํ‘œ์— ๋‚˜ํƒ€๋‚œ 3๊ฐ€์ง€ ์ด์™ธ์—๋„ ์ž๋ฐ” 8 ์ดํ›„์—์„œ๋Š” Supplier, UnaryOperator ๋“ฑ ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

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

๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์ด์šฉํ•˜๋ฉด ๊ธฐ์กด์˜ ๋ฉ”์„œ๋“œ ์ •์˜๋ฅผ ์žฌํ™œ์šฉํ•ด์„œ ๋žŒ๋‹ค์ฒ˜๋Ÿผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฒˆ ์šฐํ…Œ์ฝ”์—์„œ ๋ฏธ์…˜๋“ค์„ ์ง„ํ–‰ํ•˜๋ฉด์„œ LottoGenerate::Lotto ์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋“ค์„ ์ ‘ํ•˜์˜€๋Š”๋ฐ ์ฑ…์—์„œ ์ ‘ํ•˜๋‹ˆ ๋” ์ดํ•ดํ•˜๊ธฐ ์‰ฝ๊ณ  ์นœ์ˆ™ํ–ˆ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ์ด ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋Š” ์™œ ์ค‘์š”ํ• ๊นŒ? ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋Š” ํŠน์ • ๋ฉ”์„œ๋“œ๋งŒ์„ ํ˜ธ์ถœํ•˜๋Š” ๋žŒ๋‹ค์˜ ์ถ•์•ฝํ˜•์ด๋ผ๊ณ  ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋•Œ ๋ช…์‹œ์ ์œผ๋กœ ๋ฉ”์„œ๋“œ๋ช…์„ ์ฐธ์กฐํ•จ์œผ๋กœ์จ ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ๋‹ค. ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋Š” ์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋˜ ๊ฒƒ์ฒ˜๋Ÿผ ๋ฉ”์„œ๋“œ๋ช… ์•ž์— ๊ตฌ๋ถ„์ž(::)๋ฅผ ๋ญ์ด๋Š” ๋ฐฉ์‹์œผ๋กœ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ํ•˜๋‚˜ ๋” ๋“ค์ž๋ฉด Apple::getWeight๋Š” Apple ํด๋ž˜์Šค์— ์ •์˜๋œ getWeight์˜ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋‹ค. ์ด๊ฒƒ์€ ๋žŒ๋‹ค ํ‘œํ˜„์‹ (Apple a) -> a.getWeight()๋ฅผ ์ถ•์•ฝํ•œ ๊ฒƒ์ด๋‹ค.

๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋Š” ์„ธ ๊ฐ€์ง€ ์œ ํ˜•์œผ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  1. ์ •์  ๋ฉ”์„œ๋“œ ์ฐธ์กฐ - Integer์˜ parseInt ๋ฉ”์„œ๋“œ๋Š” Integer::parseInt๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. ๋‹ค์–‘ํ•œ ํ˜•์‹์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ์ฐธ์กฐ - String์˜ length ๋ฉ”์„œ๋“œ๋Š” String::length๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  3. ๊ธฐ์กด ๊ฐ์ฒด์˜ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ ์ฐธ์กฐ - Transcation ๊ฐ์ฒด๋ฅผ ํ• ๋‹น๋ฐ›์€ expensiveTranscation ์ง€์—ญ ๋ณ€์ˆ˜๊ฐ€ ์žˆ๊ณ , Transcation ๊ฐ์ฒด์—๋Š” getValue ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์ด๋ฅผ expensiveTransaction::getValue๋ผ๊ณ  ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ฑ…์—์„œ๋Š” 3๊ฐ€์ง€๋กœ ๊ตฌ๋ถ„ํ•˜์˜€์ง€๋งŒ ์“ฐ๋Š” ๋ฐฉ์‹์€ ๋น„์Šทํ•œ ๊ฒƒ ๊ฐ™๋‹ค.
๊ธฐ์กด์˜ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์„ ์žฌํ™œ์šฉํ•ด์„œ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด ๋ณด์•˜๋Š”๋ฐ, ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž๋ฅผ ์ด์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค.

์ƒ์„ฑ์ž ์ฐธ์กฐ

ClassName::new์ฒ˜๋Ÿผ ํด๋ž˜์Šค๋ช…๊ณผ new ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ๊ธฐ์กด ์ƒ์„ฑ์ž์˜ ์ฐธ์กฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

Supplier<Apple> c1 = () -> new Apple();
Apple a1 = c1.get();
Supplier<Apple> c1 = Apple::new;
Apple a1 = c1.get();

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์ƒ์„ฑ์ž ์ฐธ์กฐ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

๋žŒ๋‹ค, ๋ฉ”์„œ๋“œ ์ฐธ์กฐ ํ™œ์šฉํ•˜๊ธฐ

์•ž์„œ ๋ฐฐ์šด ๋žŒ๋‹ค ํ‘œํ˜„์‹๊ณผ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์‚ฌ๊ณผ ๋ฆฌ์ŠคํŠธ ์ •๋ ฌ ๋ฌธ์ œ๋ฅผ ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

1๋‹จ๊ณ„ : ์ฝ”๋“œ ์ „๋‹ฌ

        public class AppleComparator implements Comparator<Apple> {
            public int compare(Apple a1, Apple a2) {
                return a1.getWeight.compareTo(a2.getWeight());
            }
        }
        inventory.sort(new AppleComparator());

sort ๋ฉ”์„œ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค .
void sort(Comparator<? super E> c)
์ด ๋ฉ”์„œ๋“œ๋Š” Comparator ๊ฐ์ฒด๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ๋‘ ๋Œ€์ƒ์„ ๋น„๊ตํ•œ๋‹ค. ์ด sort๋ฅผ ํ™œ์šฉํ•˜์—ฌ 1๋‹จ๊ณ„ ์ฝ”๋“œ๋ฅผ ์™„์„ฑ ์‹œํ‚จ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

2๋‹จ๊ณ„ : ์ต๋ช… ํด๋ž˜์Šค ์‚ฌ์šฉ

ํ•œ ๋ฒˆ๋งŒ ์‚ฌ์šฉํ•  Comparator๋ฅผ 1๋‹จ๊ณ„ ์ฒ˜๋Ÿผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ ๋ณด๋‹ค๋Š” ์ต๋ช… ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

        inventroy.sort(new Comparator<Apple>()){
            public int compare(Apple a1, Apple a2){
                return a1.getWeight().compareTo(a2.getWeight());
            }
        }

3๋‹จ๊ณ„ : ๋žŒ๋‹ค ํ‘œํ˜„์‹ ์‚ฌ์šฉ

2๋‹จ๊ณ„ ์ฝ”๋“œ๋Š” ์•„์ง ์ฝ”๋“œ์˜ ๋ถ€ํ”ผ๊ฐ€ ์ปค๋‹ค๋ž€ ํŽธ์ด๋‹ค. ์•ž์„œ ๋ฐฐ์šด ๋žŒ๋‹ค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ฝ”๋“œ๋ฅผ ๋”์šฑ ๊ฐ„๋‹จํžˆ ๋ฆฌํŽ™ํ† ๋ง ํ•  ์ˆ˜ ์žˆ๋‹ค.

inventory.sort(comparing(apple -> apple.getWeight()));

4๋‹จ๊ณ„ : ๋ฉ”์„œ๋“œ ์ฐธ์กฐ ์‚ฌ์šฉ

๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ํ™œ์šฉํ•˜๋ฉด ๋” ๊น”๋”ํ•˜๊ฒŒ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

inventory.sort(comparing(Apple::getWeight));

์ฝ”๋“œ์˜ ๊ธธ์ด๋„ ์งง์•„์ง€๊ณ  ์ฝ”๋“œ์˜ ์˜๋ฏธ ๋˜ํ•œ ๋ช…ํ™•ํ•ด์ง„ ๊ฒƒ์„ ๋ณผ ์ˆ˜ ์žˆ๋‹ค. ์ฝ”๋“œ ์ž์ฒด๋กœ 'Apple์„ weight๋ณ„๋กœ ๋น„๊ตํ•ด์„œ inventory์— sortํ•˜๋ผ'๋ผ๋Š” ์˜๋ฏธ๋ฅผ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค. 1๋‹จ๊ณ„์™€ ๋น„๊ตํ•ด๋ณด๋ฉด ์—„์ฒญ๋‚œ ๋ณ€ํ™”๊ฐ€ ์ด๋ฃจ์–ด ์ง„ ๊ฒƒ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

๋žŒ๋‹ค ํ‘œํ˜„์‹ ์ •๋ฆฌ

  • ๋žŒ๋‹ค ํ‘œํ˜„์‹์€ ์ต๋ช… ํ•จ์ˆ˜์˜ ์ผ์ข…์ด๋‹ค. ์ด๋ฆ„์€ ์—†์ง€๋งŒ, ํŒŒ๋ผ๋ฏธํ„ฐ ๋ฆฌ์ŠคํŠธ, ๋ฐ”๋””, ๋ฐ˜ํ™˜ ํ˜•์‹์„ ๊ฐ€์ง€๋ฉฐ ์˜ˆ์™ธ๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ๋‹ค
  • ๋žŒ๋‹ค ํ‘œํ˜„์‹์œผ๋กœ ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋Š” ํ•˜๋‚˜์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋งŒ์„ ์ •์˜ํ•˜๋Š” ์ธํ„ฐํŽ˜์ด์Šค๋‹ค.
  • ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ๊ธฐ๋Œ€ํ•˜๋Š” ๊ณณ์—์„œ๋งŒ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์ด์šฉํ•ด์„œ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ถ”์ƒ ๋ฉ”์„œ๋“œ๋ฅผ ์ฆ‰์„์œผ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋žŒ๋‹ค ํ‘œํ˜„์‹ ์ „์ฒด๊ฐ€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์˜ ์ธ์Šคํ„ด์Šค๋กœ ์ทจ๊ธ‰๋œ๋‹ค.
  • java.util.function ํŒจํ‚ค์ง€๋Š” Predicate, Function<T, R>, Supplier, Consumer, BinaryOperator ๋“ฑ์„ ํฌํ•จํ•ด์„œ ์ž์ฃผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค์–‘ํ•œ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
  • ์ž๋ฐ” 8์€ Predicate์™€ Function<T, R> ๊ฐ™์€ ์ œ๋„ค๋ฆญ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค์™€ ๊ด€๋ จํ•œ ๋ฐ•์‹ฑ ๋™์ž‘์„ ํ”ผํ•  ์ˆ˜ ์žˆ๋Š” IntPredicate, IntToLongFunction ๋“ฑ๊ณผ ๊ฐ™์€ ๊ธฐ๋ณธํ˜• ํŠนํ™” ์ธํ„ฐํŽ˜์ด์Šค๋„ ์ œ๊ณตํ•œ๋‹ค.
  • ์‹คํ–‰ ์–ด๋ผ์šด๋“œ ํŒจํ„ด์„ ๋žŒ๋‹ค์™€ ํ™œ์šฉํ•˜๋ฉด ์œ ์—ฐ์„ฑ๊ณผ ์žฌ์‚ฌ์šฉ์„ฑ์„ ์ถ”๊ฐ€๋กœ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.
  • ๋žŒ๋‹ค ํ‘œํ˜„์‹์˜ ๊ธฐ๋Œ€ ํ˜•์‹์„ ๋Œ€์ƒ ํ˜•์‹์ด๋ผ๊ณ ํ•œ๋‹ค.
  • ๋ฉ”์„œ๋“œ ์ฐธ์กฐ๋ฅผ ์ด์šฉํ•˜๋ฉด ๊ธฐ์กด์˜ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์„ ์žฌ์‚ฌ์šฉํ•˜๊ณ  ์ง์ ‘ ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • Comparator, Predicate, Function ๊ฐ™์€ ํ•จ์ˆ˜ํ˜• ์ธํ„ฐํŽ˜์ด์Šค๋Š” ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์กฐํ•ฉํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค์–‘ํ•œ ๋””ํดํŠธ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

Chapter 7. ๋ณ‘๋ ฌ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์™€ ์„ฑ๋Šฅ

๋ณ‘๋ ฌ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์™€ ์„ฑ๋Šฅ

4~6์žฅ์—์„œ๋Š” ์ƒˆ๋กœ์šด ์ŠคํŠธ๋ฆผ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ ์ปฌ๋ ‰์…˜์„ ์„ ์–ธํ˜•์œผ๋กœ ์ œ์–ดํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด์•˜๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด์ œ ์†๋„์™€ ์„ฑ๋Šฅ์„ ์ƒ๊ฐํ•ด์•ผํ•œ๋‹ค. ๊ทธ ํ•ด๋‹ต์€ ๋ณ‘๋ ฌ์— ์žˆ๋‹ค.

์ž๋ฐ” 7์ด ๋“ฑ์žฅํ•˜๊ธฐ ์ด์ „ ๋ฐ์ดํ„ฐ ์ปฌ๋ ‰์…˜์„ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์–ด๋ ค์› ๋‹ค. ์šฐ์„  ๋ฐ์ดํ„ฐ๋ฅผ ์„œ๋ธŒํŒŒํŠธ๋กœ ๋ถ„ํ• ํ•˜๊ณ  ์Šค๋ ˆ๋“œ๋ฅผ ํ• ๋‹นํ•˜๊ณ  race condition์ด ๋ฐœ์ƒํ•˜์ง€ ์•Š๋„๋ก ๋™๊ธฐํ™”๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉฐ ๋งˆ์ง€๋ง‰์œผ๋กœ ๋ถ€๋ถ„ ๊ฒฐ๊ณผ๋ฅผ ํ•ฉ์ณ์•ผํ•œ๋‹ค. ์ด ์–ผ๋งˆ๋‚˜ ์–ด๋ ค์šด๊ฐ€!
์ž๋ฐ” 7์€ ๋” ์‰ฝ๊ฒŒ ๋ณ‘๋ ฌํ™”๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ฉด์„œ ์—๋Ÿฌ๋ฅผ ์ตœ์†Œํ™”ํ•  ์ˆ˜ ์žˆ๋„๋ก ํฌํฌ/์กฐ์ธ ํ”„๋ ˆ์ž„์›Œํฌ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.

ํฌํฌ/์กฐ์ธ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์†Œ๊ฐœํ•˜๊ธฐ ์ „ ์šฐ๋ฆฌ ์žฅ์˜ ํ•ต์‹ฌ์ธ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ์ดํ„ฐ ์ปฌ๋ ‰์…˜ ๊ด€๋ จ ๋™์ž‘์„ ์–ผ๋งˆ๋‚˜ ์‰ฝ๊ฒŒ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ์„ค๋ช…ํ•œ๋‹ค. ์ŠคํŠธ๋ฆผ์„ ์ด์šฉํ•˜๋ฉด ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.

๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ

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

    public long parallelSum(long n) {
        return Stream.iterate(1l, i -> i + 1)
                .limit(n)
                .parallel()
                .reduce(0L, Long::sum);
    }

1๋ถ€ํ„ฐ n๊นŒ์ง€ ๋ชจ๋“  ์ˆซ์ž๋ฅผ ๋”ํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์ค‘๊ฐ„์— parallel๋ฅผ ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
๋ฐ˜๋Œ€๋กœ sequential์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์„ ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค.
์ด ๋‘ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ์–ด๋–ค ์—ฐ์‚ฐ์„ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•˜๊ณ  ์–ด๋–ค ์—ฐ์‚ฐ์„ ์ˆœ์ฐจ๋กœ ์‹คํ–‰ํ• ์ง€ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.
parallel๊ณผ sequential ๋‘ ๋ฉ”์„œ๋“œ ์ค‘ ์ตœ์ข…์ ์œผ๋กœ ํ˜ธ์ถœ๋œ ๋ฉ”์„œ๋“œ๊ฐ€ ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ์— ์˜ํ–ฅ์„ ๋ฏธ์นœ๋‹ค.

์ŠคํŠธ๋ฆผ ์„ฑ๋Šฅ ์ธก์ •

๋ณ‘๋ ฌํ™”๋ฅผ ์™œ ์‚ฌ์šฉํ• ๊นŒ? ๋‹น์—ฐํžˆ ์„ฑ๋Šฅ, ์†๋„ ๋•Œ๋ฌธ์ด ์•„๋‹๊นŒ๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค.
๋ฌด์กฐ๊ฑด ๋ณ‘๋ ฌํ™”๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ์ด ์ข‹์•„์งˆ๊นŒ? ์ด๋Ÿฌํ•œ ์ƒ๊ฐ์€ ์œ„ํ—˜ํ•œ ์ƒ๊ฐ์ด๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ์–ด๋–จ๋•Œ ๋ณ‘๋ ฌํ™”๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ˆœ์ฐจ๋ฅผ ์‚ฌ์šฉํ• ๊นŒ? ์ง์ ‘ ์†๋„๋ฅผ ์ธก์ •ํ•˜์—ฌ ๋น ๋ฅธ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค!
iterate๋ฅผ ์ด์šฉํ•ด์„œ 1๋ถ€ํ„ฐ n๊นŒ์ง€ ๋”ํ•˜๋Š” ์˜ˆ์ œ๋ฅผ ๋ณด์ž
์‹ค์ œ๋กœ ๋ณ‘๋ ฌํ™”๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒƒ๋ณด๋‹ค ์ˆœ์ฐจ์ ์œผ๋กœ ๊ณ„์‚ฐํ•œ ๋ฐฉ๋ฒ•์ด ์•ฝ 5๋ฐฐ ๋นจ๋ž๋‹ค. ์™œ ์ด๋Ÿฐ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ ๊ฒƒ์ผ๊นŒ?
์šฐ๋ฆฌ๋Š” Iterate์— ์ง‘์ค‘ํ•ด์•ผํ•œ๋‹ค. iterate๋กœ ์ˆซ์ž๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ํ•˜๋‚˜์”ฉ ์ƒ์‚ฐํ•˜๋ฏ€๋กœ ์ „์ฒด ์ˆซ์ž๋ฅผ ํ•œ๊บผ๋ฒˆ์— ๋ฐ›์•„ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌํ•˜๋Š” ๋ณ‘๋ ฌ๋ฐฉ์‹์ด ๋” ๋Š๋ฆฐ ๊ฒƒ์ด๋‹ค.
์ด์ฒ˜๋Ÿผ ๋ณ‘๋ ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๊นŒ๋‹ค๋กญ๊ณ  ๋•Œ๋กœ๋Š” ์ดํ•ดํ•˜๊ธฐ ์–ด๋ ค์šด ํ•จ์ •์ด ์ˆจ์–ด์žˆ๋‹ค. ์‹ฌ์ง€์–ด ๋ณ‘๋ ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ์˜คํžˆ๋ ค ์ „์ฒด ํ”„๋กœ๊ทธ๋žจ์˜ ์„ฑ๋Šฅ์ด ๋” ๋‚˜๋น ์งˆ ์ˆ˜๋„ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ parallel ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ–ˆ์„ ๋•Œ ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ค ์ผ์ด ์ผ์–ด๋‚˜๋Š”์ง€ ๊ผญ ์ดํ•ดํ•ด์•ผํ•œ๋‹ค.

๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ

  • ํ™•์‹ ์ด ์„œ์ง€ ์•Š์œผ๋ฉด ์ง์ ‘ ์ธก์ •ํ•˜๋ผ. ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์‰ฝ๊ฒŒ ๋ฐ”๊ฟ€ ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ฌด์กฐ๊ฑด ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๊ฒƒ์ด ๋Šฅ์‚ฌ๋Š” ์•„๋‹ˆ๋‹ค. ์ด๋ฏธ ์‚ดํŽด๋ณธ ๊ฒƒ ์ฒ˜๋Ÿผ ์–ธ์ œ๋‚˜ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์ด ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ๋ณด๋‹ค ๋น ๋ฅธ ๊ฒƒ์€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ๋”์šฑ์ด ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์˜ ์ˆ˜ํ–‰ ๊ณผ์ •์€ ํˆฌ๋ช…ํ•˜์ง€ ์•Š์„ ๋•Œ๊ฐ€ ๋งŽ๋‹ค. ๋”ฐ๋ผ์„œ ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ๊ณผ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์ค‘ ์–ด๋–ค ๊ฒƒ์ด ์ข‹์„ ์ง€ ๋ชจ๋ฅด๊ฒ ๋‹ค๋ฉด ์ ์ ˆํ•œ ๋ฒค์น˜๋งˆํฌ๋กœ ์ง์ ‘ ์„ฑ๋Šฅ์„ ์ธก์ •ํ•˜๋Š” ๊ฒƒ์ด ๋ฐ”๋žŒ์งํ•˜๋‹ค.
  • ๋ฐ•์‹ฑ์„ ์ฃผ์˜ํ•˜๋ผ. ์ž๋™ ๋ฐ•์‹ฑ๊ณผ ์–ธ๋ฐ•์‹ฑ์€ ์„ฑ๋Šฅ์„ ํฌ๊ฒŒ ์ €ํ•˜์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์š”์†Œ๋‹ค.
  • ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ๋ณด๋‹ค ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์—์„œ ์„ฑ๋Šฅ์ด ๋–จ์–ด์ง€๋Š” ์—ฐ์‚ฐ์ด ์žˆ๋‹ค. ํŠนํžˆ limit๋‚˜ findFirst์ฒ˜๋Ÿผ ์š”์†Œ์˜ ์ˆœ์„œ์— ์˜์กดํ•˜๋Š” ์—ฐ์‚ฐ์„ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์—์„œ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด ๋น„์‹ผ ๋น„์šฉ์„ ์น˜๋Ÿฌ์•ผ ํ•œ๋‹ค.
  • ์ŠคํŠธ๋ฆผ์—์„œ ์ˆ˜ํ–‰ํ•˜๋Š” ์ „์ฒด ํŒŒ์ดํ”„๋ผ์ธ ์—ฐ์‚ฐ ๋น„์šฉ์„ ๊ณ ๋ คํ•˜๋ผ. ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ์š”์†Œ ์ˆ˜๊ฐ€ N์ด๊ณ  ํ•˜๋‚˜์˜ ์š”์†Œ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š”๋ฐ ๋“œ๋Š” ๋น„์šฉ์„ Q๋ผ ํ•˜๋ฉด ์ „์ฒด ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ ์ฒ˜๋ฆฌ ๋น„์šฉ์„ N*Q๋กœ ์˜ˆ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค. Q ๊ฐ€ ๋†’์•„์ง„๋‹ค๋Š” ๊ฒƒ์€ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์„ฑ๋Šฅ์„ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Œ์„ ์˜๋ฏธํ•œ๋‹ค.
  • ์†Œ๋Ÿ‰์˜ ๋ฐ์ดํ„ฐ์—์„œ๋Š” ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์ด ๋„์›€์ด ๋˜์ง€ ์•Š๋Š”๋‹ค.
  • ์ŠคํŠธ๋ฆผ์„ ๊ตฌ์„ฑํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ์ ์ ˆํ•œ์ง€ ํ™•์ธํ•˜๋ผ. ์˜ˆ๋ฅผ ๋“ค์–ด ArrayList๋ฅผ LinkedList๋ณด๋‹ค ํšจ์œจ์ ์œผ๋กœ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ŠคํŠธ๋ฆผ์˜ ํŠน์„ฑ๊ณผ ํŒŒ์ดํ”„๋ผ์ธ์˜ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์ด ์ŠคํŠธ๋ฆผ์˜ ํŠน์„ฑ์„ ์–ด๋–ป๊ฒŒ ๋ฐ”๊พธ๋Š”์ง€์— ๋”ฐ๋ผ ๋ถ„ํ•ด ๊ณผ์ •์˜ ์„ฑ๋Šฅ์ด ๋‹ฌ๋ผ์งˆ ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด SIZED ์ŠคํŠธ๋ฆผ์€ ์ •ํ™•ํžˆ ๊ฐ™์€ ํฌ๊ธฐ์˜ ๋‘ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ถ„ํ• ํ•  ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ ํšจ๊ณผ์ ์œผ๋กœ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋ฉด ํ•„ํ„ฐ ์—ฐ์‚ฐ์ด ์žˆ์œผ๋ฉด ์ŠคํŠธ๋ฆผ์˜ ๊ธธ์ด๋ฅผ ์˜ˆ์ธกํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ํšจ๊ณผ์ ์œผ๋กœ ์ŠคํŠธ๋ฆผ์„ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์„์ง€ ์•Œ ์ˆ˜ ์—†๊ฒŒ ๋œ๋‹ค.
  • ์ตœ์ข… ์—ฐ์‚ฐ์˜ ๋ณ‘ํ•ฉ ๊ณผ์ • ๋น„์šฉ์„ ์‚ดํŽด๋ณด๋ผ.
  • ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ๊ณผ ๋ณ‘๋ ฌ ๊ณ„์‚ฐ์—์„œ ๊ณต์œ ๋œ ๊ฐ€๋ณ€ ์ƒํƒœ๋ฅผ ํ”ผํ•ด์•ผ ํ•œ๋‹ค. ์ด๋Š” ์„ฑ๋Šฅ์˜ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ ์™„์ „ํžˆ ๋‹ค๋ฅธ ๊ฐ’์ด ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

ํฌํฌ/์กฐ์ธ ํ”„๋ ˆ์ž„ ์›Œํฌ

Spliterator ์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ ์ชผ๊ฐœ๊ธฐ

๋งˆ์น˜๋ฉฐ

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

Chapter 4. ์ŠคํŠธ๋ฆผ ์†Œ๊ฐœ

์ŠคํŠธ๋ฆผ ์†Œ๊ฐœ

์ŠคํŠธ๋ฆผ์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

์ŠคํŠธ๋ฆผ์€ ์ž๋ฐ” 8 API์— ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ์ด๋‹ค. ์ŠคํŠธ๋ฆผ์„ ์ด์šฉํ•˜๋ฉด ์„ ์–ธํ˜•์œผ๋กœ ์ปฌ๋ ‰์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค. ๋จผ์ € ์ž๋ฐ” 7 ์ฝ”๋“œ์™€ ์ž๋ฐ” 8 ์ฝ”๋“œ๋ฅผ ๋น„๊ตํ•ด๋ณด์ž.

List<Dish> lowCaloricDishes = new ArrayList<>();
        for (Dish dish : menu) {
            if (dish.getCalories() < 400) {
                lowCaloricDishes.add(dish);
            }
        }
        Collections.sort(lowCaloricDishes, new Comparator<Dish>() {
            public int compare(Dish dish1, Dish dish2) {
                return Integer.compare(dish1.getCalories, dish2.getCalories());
            }
        });
        List<String> lowCaloricDishesName = new ArrayList<>();
        for (Dish dish : lowCaloricDishes) {
            lowCaloricDishesName.add(dish.getName());
        }
List<String> lowCaloricDishesName = 
                menu.stream()
                    .filter(d -> d.getCalories() < 400)
                    .sorted(comparing(Dish::getCalories))
                    .map(Dish::getName)
                    .collect(toList());

์นผ๋กœ๋ฆฌ๊ฐ€ 400 ์ดํ•˜์ธ ์Œ์‹๋“ค์„ ๊ตฌํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž๋ฐ” ์ปฌ๋ ‰์…˜๊ณผ ์ŠคํŠธ๋ฆผ ๋‘๊ฐ€์ง€ ๋ฐฉ๋ฒ•์œผ๋กœ ๊ตฌํ˜„ํ•œ ๊ฒƒ์ด๋‹ค.

์ž๋ฐ” 8์˜ ์ŠคํŠธ๋ฆผ API์˜ ํŠน์ง•

  • ์„ ์–ธํ˜• : ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ๊ฐ€๋…์„ฑ์ด ์ข‹์•„์ง„๋‹ค.
  • ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ์Œ : ์œ ์—ฐ์„ฑ์ด ์ข‹์•„์ง„๋‹ค.
  • ๋ณ‘๋ ฌํ™” : ์„ฑ๋Šฅ์ด ์ข‹์•„์ง„๋‹ค.

์ŠคํŠธ๋ฆผ ์‹œ์ž‘ํ•˜๊ธฐ

์ŠคํŠธ๋ฆผ์ด๋ž€ ์ •ํ™•ํžˆ ๋ฌด์—‡์ผ๊นŒ? ์ŠคํŠธ๋ฆผ์ด๋ž€ '๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์—ฐ์‚ฐ์„ ์ง€์›ํ•˜๋„๋ก ์†Œ์Šค์—์„œ ์ถ”์ถœ๋œ ์—ฐ์†๋œ ์š”์†Œ'๋กœ ์ •์˜ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ •์˜์— ๋‚˜์™€์žˆ๋Š” ๋‹จ์–ด๋ฅผ ํ•˜๋‚˜์”ฉ ์‚ดํŽด๋ณด์ž

์ŠคํŠธ๋ฆผ ์ •์˜ ์‚ดํŽด๋ณด๊ธฐ

  • ์—ฐ์†๋œ ์š”์†Œ : ์ปฌ๋ ‰์…˜๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ŠคํŠธ๋ฆผ์€ ํŠน์ • ์š”์†Œ ํ˜•์‹์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ์—ฐ์†๋œ ๊ฐ’ ์ง‘ํ•ฉ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ปฌ๋ ‰์…˜์€ ์ž๋ฃŒ๊ตฌ์กฐ์ด๋ฏ€๋กœ ์ปฌ๋ ‰์…˜์—์„œ๋Š” ์‹œ๊ฐ„๊ณผ ๊ณต๊ฐ„์˜ ๋ณต์žก์„ฑ๊ณผ ๊ด€๋ จ๋œ ์š”์†Œ ์ €์žฅ ๋ฐ ์ ‘๊ทผ ์—ฐ์‚ฐ์ด ์ฃผ๋ฅผ ์ด๋ฃฌ๋‹ค. ๋ฐ˜๋ฉด ์ŠคํŠธ๋ฆผ์€ filter, sorted, map์ฒ˜๋Ÿผ ํ‘œํ˜„ ๊ณ„์‚ฐ์‹์ด ์ฃผ๋ฅผ ์ด๋ฃฌ๋‹ค. ์ฆ‰, ์ปฌ๋ ‰์…˜์˜ ์ฃผ์ œ๋Š” ๋ฐ์ดํ„ฐ๊ณ  ์ŠคํŠธ๋ฆผ์˜ ์ฃผ์ œ๋Š” ๊ณ„์‚ฐ์ด๋‹ค.
  • ์†Œ์Šค : ์ŠคํŠธ๋ฆผ์€ ์ปฌ๋ ‰์…˜, ๋ฐฐ์—ด, I/O ์ž์› ๋“ฑ์˜ ๋ฐ์ดํ„ฐ ์ œ๊ณต ์†Œ์Šค๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์†Œ๋น„ํ•œ๋‹ค. ์ •๋ ฌ๋œ ์ปฌ๋ ‰์…˜์œผ๋กœ ์ŠคํŠธ๋ฆผ์„ ์ƒ์„ฑํ•˜๋ฉด ์ •๋ ฌ์ด ๊ทธ๋Œ€๋กœ ์œ ์ง€๋œ๋‹ค. ์ฆ‰, ๋ฆฌ์ŠคํŠธ๋กœ ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ค๋ฉด ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋Š” ๋ฆฌ์ŠคํŠธ์˜ ์š”์†Œ์™€ ๊ฐ™์€ ์ˆœ์„œ๋ฅผ ์œ ์ง€ํ•œ๋‹ค.
  • ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์—ฐ์‚ฐ : ์ŠคํŠธ๋ฆผ์€ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ์ง€์›ํ•˜๋Š” ์—ฐ์‚ฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋น„์Šทํ•œ ์—ฐ์‚ฐ์„ ์ง€์›ํ•œ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด filter, map, reduce, find, match, sort ๋“ฑ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ์€ ์ˆœ์ฐจ์ ์œผ๋กœ ๋˜๋Š” ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ŠคํŠธ๋ฆผ ํŠน์ง•

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

์•„๋ž˜ ์˜ˆ์ œ ์ฝ”๋“œ๋ฅผ ํ†ตํ•ด ์ŠคํŠธ๋ฆผ์˜ ์ •์˜์™€ ํŠน์ง•์„ ๋‹ค์‹œ ํ•œ๋ฒˆ ์‚ดํŽด๋ณด์ž

List<String> threeHighCaloricDishNames =
                menu.stream()
                    .filter(dish -> dish.getCalories() > 300)
                    .map(Dish::getName)
                    .limit(3)
                    .collect(toList());

์šฐ์„  ์š”๋ฆฌ ๋ฆฌ์ŠคํŠธ๋ฅผ ํฌํ•จํ•˜๋Š” menu์— stream ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์„œ ์ŠคํŠธ๋ฆผ์„ ์–ป์—ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฐ์ดํ„ฐ ์†Œ์Šค๋Š” ์š”๋ฆฌ ๋ฆฌ์ŠคํŠธ(๋ฉ”๋‰ด)์ด๋‹ค. ๋ฐ์ดํ„ฐ ์†Œ์Šค๋Š” ์—ฐ์†๋œ ์š”์†Œ๋ฅผ ์ŠคํŠธ๋ฆผ์— ์ œ๊ณตํ•œ๋‹ค. ๋‹ค์Œ์œผ๋กœ ์ŠคํŠธ๋ฆผ์— filter, map, limit, collect๋กœ ์ด์–ด์ง€๋Š” ์ผ๋ จ์˜ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์—ฐ์‚ฐ์„ ์ ์šฉํ•œ๋‹ค. collect๋ฅผ ์ œ์™ธํ•œ ๋ชจ๋“  ์—ฐ์‚ฐ์€ ์„œ๋กœ ํŒŒ์ดํ”„๋ผ์ธ์„ ํ˜•์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

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

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

์™ธ๋ถ€ ๋ฐ˜๋ณต๊ณผ ๋‚ด๋ถ€ ๋ฐ˜๋ณต

์ปฌ๋ ‰์…˜๊ณผ ์ŠคํŠธ๋ฆผ์˜ ๋˜๋‹ค๋ฅธ ์ฐจ์ด์ ์€ ๋ฐ์ดํ„ฐ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ ๋ฐฉ๋ฒ•์ด๋‹ค.
์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์š”์†Œ๋ฅผ ๋ฐ˜๋ณตํ•ด์•ผ ํ•œ๋‹ค. ์ด๋ฅผ ์™ธ๋ถ€ ๋ฐ˜๋ณต์ด๋ผ๊ณ  ํ•œ๋‹ค. ๋ฐ˜๋ฉด ์ŠคํŠธ๋ฆผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋Š” ๋‚ด๋ถ€ ๋ฐ˜๋ณต์„ ์‚ฌ์šฉํ•œ๋‹ค.

์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ

List<String> threeHighCaloricDishNames =
                menu.stream()
                    .filter(dish -> dish.getCalories() > 300)
                    .map(Dish::getName)
                    .limit(3)
                    .collect(toList());

์œ„์˜ ์ฝ”๋“œ์—์„œ ์—ฐ์‚ฐ์„ ๋‘ ๊ทธ๋ฃน์œผ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • filter, map, limit๋Š” ์„œ๋กœ ์—ฐ๊ฒฐ๋˜์–ด ํŒŒ์ดํ”„๋ผ์ธ์„ ํ˜•์„ฑํ•œ๋‹ค.
  • collect๋กœ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‹คํ–‰ํ•œ ๋‹ค์Œ์— ๋‹ซ๋Š”๋‹ค.

์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ์„ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์ด๋ผ๊ณ  ํ•˜๋ฉฐ, ์ŠคํŠธ๋ฆผ์„ ๋‹ซ๋Š” ์—ฐ์‚ฐ์„ ์ตœ์ข… ์—ฐ์‚ฐ์ด๋ผ๊ณ  ํ•œ๋‹ค. ์ค‘๊ฐ„ ์—ฐ์‚ฐ๊ณผ ์ตœ์ข… ์—ฐ์‚ฐ์€ ์ŠคํŠธ๋ฆผ์—์„œ ์ค‘์š”ํ•œ ๊ตฌ๋ถ„์ด๋‹ค.

์ค‘๊ฐ„ ์—ฐ์‚ฐ

์ค‘๊ฐ„ ์—ฐ์‚ฐ์€ filter๋‚˜ sorted๊ฐ™์€ ์—ฐ์‚ฐ์ด๋ฉฐ ๋‹ค๋ฅธ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ ์—ฌ๋Ÿฌ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์„ ์—ฐ๊ฒฐํ•ด์„œ ์งˆ์˜๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์ค‘๊ฐ„์—ฐ์‚ฐ์˜ ์ค‘์š”ํ•œ ํŠน์ง•์€ ๋‹จ๋ง ์—ฐ์‚ฐ์„ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์— ์‹คํ–‰ํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์•„๋ฌด ์—ฐ์‚ฐ๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ, ์ฆ‰ ๊ฒŒ์œผ๋ฅด๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.

์ตœ์ข… ์—ฐ์‚ฐ

์ตœ์ข… ์—ฐ์‚ฐ์€ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ๊ฒฐ๊ณผ๋ฅผ ๋„์ถœํ•œ๋‹ค. ๋ณดํ†ต ์ตœ์ข… ์—ฐ์‚ฐ์— ์˜ํ•ด List, Integer, void ๋“ฑ ์ŠคํŠธ๋ฆผ ์ด์™ธ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

๋งˆ์น˜๋ฉฐ

  • ์ŠคํŠธ๋ฆผ์€ ์†Œ์Šค์—์„œ ์ถ”์ถœ๋œ ์—ฐ์† ์š”์†Œ๋กœ, ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์—ฐ์‚ฐ์„ ์ง€์›ํ•œ๋‹ค.
  • ์ŠคํŠธ๋ฆผ์€ ๋‚ด๋ถ€ ๋ฐ˜๋ณต์„ ์ง€์›ํ•œ๋‹ค. ๋‚ด๋ถ€ ๋ฐ˜๋ณต์€ filter, map, sorted ๋“ฑ์˜ ์—ฐ์‚ฐ์œผ๋กœ ๋ฐ˜๋ณต์„ ์ถ”์ƒํ™”ํ•œ๋‹ค.
  • ์ŠคํŠธ๋ฆผ์—๋Š” ์ค‘๊ฐ„ ์—ฐ์‚ฐ๊ณผ ์ตœ์ข… ์—ฐ์‚ฐ์ด ์žˆ๋‹ค.
  • ์ค‘๊ฐ„ ์—ฐ์‚ฐ์€ filter์™€ map์ฒ˜๋Ÿผ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋ฉด์„œ ๋‹ค๋ฅธ ์—ฐ์‚ฐ๊ณผ ์—ฐ๊ฒฐ๋˜๋Š” ์—ฐ์‚ฐ์ด๋‹ค. ์ค‘๊ฐ„ ์—ฐ์‚ฐ์„ ์ด์šฉํ•ด์„œ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์œผ๋กœ๋Š” ์–ด๋–ค ๊ฒฐ๊ณผ๋„ ์ƒ์„ฑํ•  ์ˆ˜ ์—†๋‹ค.
  • forEach๋‚˜ count์ฒ˜๋Ÿผ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์„ ์ฒ˜๋ฆฌํ•ด์„œ ์ŠคํŠธ๋ฆผ์ด ์•„๋‹Œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์—ฐ์‚ฐ์„ ์ตœ์ข… ์—ฐ์‚ฐ์ด๋ผ๊ณ  ํ•œ๋‹ค.
  • ์ŠคํŠธ๋ฆผ ์š”์†Œ๋Š” ์š”์ฒญํ•  ๋•Œ ๊ฒŒ์œผ๋ฅด๊ฒŒ ๊ณ„์‚ฐ๋œ๋‹ค.

Chapter 5. ์ŠคํŠธ๋ฆผ ํ™œ์šฉ

์ŠคํŠธ๋ฆผ ํ™œ์šฉ

์ŠคํŠธ๋ฆผ API๋Š” ํ•„ํ„ฐ๋ง, ์Šฌ๋ผ์ด์‹ฑ, ๋งคํ•‘, ๊ฒ€์ƒ‰, ๋งค์นญ, ๋ฆฌ๋“€์‹ฑ ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋ฒˆ ์ฑ•ํ„ฐ์—์„œ๋Š” ์ŠคํŠธ๋ฆผ์˜ ๋‹ค์–‘ํ•œ ์—ฐ์‚ฐ๋“ค์„ ์‚ดํŽด๋ณด๊ณ  ์ง์ ‘ ์‚ฌ์šฉํ•˜๋ฉฐ ๊ณต๋ถ€ํ•  ๊ฒƒ์ด๋‹ค.

ํ•„ํ„ฐ๋ง

์ŠคํŠธ๋ฆผ ์ธํ„ฐํŽ˜์ด์Šค๋Š” filter ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค. filter ๋ฉ”์„œ๋“œ๋Š” ํ”„๋ ˆ๋””์ผ€์ดํŠธ๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ํ”„๋ ˆ๋””์ผ€์ดํŠธ์™€ ์ผ์น˜ํ•˜๋Š” ๋ชจ๋“  ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

List<Dish> vegetarianMenu = menu.stream().filter(Dish::isVegetarian).collect(toList());

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ ๋ชจ๋“  ์ฑ„์‹์š”๋ฆฌ๋ฅผ ํ•„ํ„ฐ๋งํ•ด์„œ ์ฑ„์‹ ๋ฉ”๋‰ด๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

๊ณ ์œ  ์š”์†Œ ํ•„ํ„ฐ๋ง (์ค‘๋ณต ์ œ๊ฑฐ)

์ŠคํŠธ๋ฆผ์€ ๊ณ ์œ  ์š”์†Œ๋กœ ์ด๋ฃจ์–ด์ง„ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” distinct ๋ฉ”์„œ๋“œ๋„ ์ง€์›ํ•œ๋‹ค.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);
        numbers.stream().filter(i -> i % 2 ==0).distinct().forEach(System.out::println);

์œ„์˜ ์ฝ”๋“œ๋Š” ๋ฆฌ์ŠคํŠธ์˜ ๋ชจ๋“  ์ง์ˆ˜๋ฅผ ์„ ํƒํ•˜๊ณ  ์ค‘๋ณต์„ ํ•„ํ„ฐ๋งํ•œ๋‹ค.

์ŠคํŠธ๋ฆผ ์Šฌ๋ผ์ด์‹ฑ

์ž๋ฐ” 9์—์„œ๋Š” ์ŠคํŠธ๋ฆผ ์š”์†Œ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์„ ํƒํ•  ์ˆ˜ ์žˆ๋„๋ก takeWhile, dropWhile ๋‘ ๊ฐ€์ง€ ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค.

TAKEWHILE ํ™œ์šฉ

๋งŒ์•ฝ ๋ฉ”๋‰ด์—์„œ 320 ์นผ๋กœ๋ฆฌ ์ดํ•˜์˜ ์š”๋ฆฌ๋ฅผ ์„ ํƒํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด filter๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด ๋ฐฉ๋ฒ•์€ ์ „์ฒด ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ๊ฐ ์š”์†Œ์— ํ”„๋ ˆ๋””์ผ€์ดํŠธ๋ฅผ ์ ์šฉํ•˜๊ฒŒ ๋œ๋‹ค. ๋งŒ์•ฝ List๊ฐ€ ์ •๋ ฌ๋˜์–ด ์žˆ๋‹ค๋ฉด, filter ๋Œ€์‹  takeWhile ์—ฐ์‚ฐ์„ ์ด์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

List<Dish> slicedMenu1 = specialMenu.stream().takeWhile(dish -> dish.getCalories() < 320).collect(toList());

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ takeWhile์„ ์‚ฌ์šฉํ•˜์—ฌ 320 ์นผ๋กœ๋ฆฌ๊ฐ€ ๋„˜๋Š” ์š”๋ฆฌ๊ฐ€ ๋‚˜์˜จ๋‹ค๋ฉด ๋ฐ˜๋ณต ์ž‘์—…์„ ์ค‘๋‹จํ•œ๋‹ค.
๊ทธ๋ ‡๋‹ค๋ฉด ๋‚˜๋จธ์ง€ ์š”์†Œ๋“ค์€ ์–ด๋–ป๊ฒŒ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

List<Dish> slicedMenu2 = specialMenu.stream().dropWhile(dish -> dish.getCalories() < 320).collect(toList());

dropWhile์„ ์‚ฌ์šฉํ•˜๊ฒŒ๋˜๋ฉด ๋ฐ˜๋Œ€ ์ž‘์—…์„ ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ŠคํŠธ๋ฆผ ์ถ•์†Œ

์ŠคํŠธ๋ฆผ์€ ์ฃผ์–ด์ง„ ๊ฐ’ ์ดํ•˜์˜ ํฌ๊ธฐ๋ฅผ ๊ฐ–๋Š” ์ƒˆ๋กœ์šด ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” limit(n) ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค. ๋‹ค์Œ ์ฝ”๋“œ๋Š” 300์นผ๋กœ๋ฆฌ ์ด์ƒ์˜ ์„ธ ์š”๋ฆฌ๋ฅผ ์„ ํƒํ•ด์„œ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

List<Dish> dishes = specialMenu.stream().filter(dish -> dish.getCalories() > 300).limit(3).collect(toList());

์š”์†Œ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

์ŠคํŠธ๋ฆผ์€ ์ฒ˜์Œ n๊ฐœ ์š”์†Œ๋ฅผ ์ œ์™ธํ•œ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” skip(n) ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค. ๋งŒ์•ฝ n๊ฐœ ์ดํ•˜์˜ ์š”์†Œ๋ฅผ ํฌํ•จํ•˜๋Š” ์ŠคํŠธ๋ฆผ์— skip(n)์„ ํ˜ธ์ถœํ•˜๋ฉด ๋นˆ ์ŠคํŠธ๋ฆผ์ด ๋ฐ˜ํ™˜๋œ๋‹ค. ์•„๋ž˜์˜ ์ฝ”๋“œ๋Š” 300์นผ๋กœ๋ฆฌ ์ด์ƒ์˜ ์š”๋ฆฌ ์ค‘ ์ฒ˜์Œ ๋‘ ์š”๋ฆฌ๋ฅผ ๊ฑด๋„ˆ๋›ด ๋‹ค์Œ 300 ์นผ๋กœ๋ฆฌ๊ฐ€ ๋„˜๋Š” ๋‚˜๋จธ์ง€ ์š”๋ฆฌ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

List<Dish> dishes = menu.stream().filter(d -> d.getCalories() > 300).skip(2).collect(toList());

๋งคํ•‘

์ŠคํŠธ๋ฆผ์˜ ๊ฐ ์š”์†Œ์— ํ•จ์ˆ˜ ์ ์šฉํ•˜๊ธฐ

์ŠคํŠธ๋ฆผ์€ ํ•จ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š” map ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค. ์ธ์ˆ˜๋กœ ์ œ๊ณต๋œ ํ•จ์ˆ˜๋Š” ๊ฐ ์š”์†Œ์— ์ ์šฉ๋˜๋ฉฐ ํ•จ์ˆ˜๋ฅผ ์ ์šฉํ•œ ๊ฒฐ๊ณผ๊ฐ€ ์ƒˆ๋กœ์šด ์š”์†Œ๋กœ ๋งคํ•‘๋œ๋‹ค. map๋ฉ”์„œ๋“œ ๋ผ๋ฆฌ ์—ฐ๊ฒฐ ํ•  ์ˆ˜ ์žˆ๋‹ค.

List<String> dishNames = menu.stream().map(Dish::getName).collect(toList());

์œ„์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ map ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์š”๋ฆฌ์˜ ์ด๋ฆ„์„ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ๋‹ค.

์ŠคํŠธ๋ฆผ ํ‰๋ฉดํ™”(flatMap)

flatMap์„ ์ดํ•ดํ•˜๊ธฐ ์ „์— ์˜ˆ์ œ๋ฅผ ํ•˜๋‚˜ ๋“ค์–ด ๋ณด๊ฒ ๋‹ค.
๋ฆฌ์ŠคํŠธ์—์„œ ๊ณ ์œ  ๋ฌธ์ž๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ฐ˜ํ™˜ํ•ด๋ณด์ž. ์˜ˆ๋ฅผ๋“ค์–ด ["Hello", "World"] ๋ฆฌ์ŠคํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด ๊ฒฐ๊ณผ๋กœ ["H", "e", "l", "o", "W", "r", "d"]๋ฅผ ํฌํ•จํ•˜๋Š” ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋ฐ˜ํ™˜๋˜์–ด์•ผ ํ•œ๋‹ค.
์•ž์„œ ๋ฐฐ์šด distinct()๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ค‘๋ณต๋œ ๋ฌธ์ž๋ฅผ ํ•„ํ„ฐ๋งํ•˜์—ฌ ํ•ด๊ฒฐํ•œ๋‹ค๋Š” ์ƒ๊ฐ์„ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ๋‹ค.

words.stream().map(word -> word.split("")).distinct().collect(toList());

์œ„ ์ฝ”๋“œ์—์„œ map์œผ๋กœ ์ „๋‹ฌํ•œ ๋žŒ๋‹ค๋Š” ๊ฐ ๋‹จ์–ด์˜ String[]์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ์ ์ด ๋ฌธ์ œ๋‹ค. ๋”ฐ๋ผ์„œ map ๋ฉ”์†Œ๋“œ๊ฐ€ ๋ฐ˜ํ™˜ํ•œ ์ŠคํŠธ๋ฆผ์˜ ํ˜•์‹์€ Stream<String[]>์ด๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ์›ํ•˜๋Š” ๊ฒƒ์€ ๋ฌธ์ž์—ด ์ŠคํŠธ๋ฆผ์„ ํ‘œํ˜„ํ•  Stream ์ด๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด ๋ฌธ์ œ๋Š” flatMap ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

flatMap์„ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์Œ์ฒ˜๋Ÿผ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

List<String> uniqueCharacters = words.stream().map(word -> word.split("")).flatMap(Arrays::stream).distinct().collect(toList());

flatMap์€ ๊ฐ ๋ฐฐ์—ด์„ ์ŠคํŠธ๋ฆผ์ด ์•„๋‹ˆ๋ผ ์ŠคํŠธ๋ฆผ์˜ ์ฝ˜ํ…์ธ ๋กœ ๋งคํ•‘ํ•œ๋‹ค. ์ฆ‰, map๊ณผ ๋‹ฌ๋ฆฌ flatMap์€ ํ•˜๋‚˜์˜ ํ‰๋ฉดํ™”๋œ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์š”์•ฝํ•˜์ž๋ฉด flatMap์€ ์ŠคํŠธ๋ฆผ์˜ ๊ฐ ๊ฐ’์„ ๋‹ค๋ฅธ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋งŒ๋“  ๋‹ค์Œ ๋ชจ๋“  ์ŠคํŠธ๋ฆผ์„ ํ•˜๋‚˜์˜ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

๊ฒ€์ƒ‰๊ณผ ๋งค์นญ

ํŠน์ • ์†์„ฑ์ด ๋ฐ์ดํ„ฐ ์ง‘ํ•ฉ์— ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋„ ์ž์ฃผ ์‚ฌ์šฉ๋œ๋‹ค. ์ŠคํŠธ๋ฆผ API๋Š” allMatch, anyMatch, noneMatch, findFirst, findAny ๋“ฑ ๋‹ค์–‘ํ•œ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.

anyMatch

ํ”„๋ ˆ๋””์ผ€์ดํŠธ๊ฐ€ ์ ์–ด๋„ ํ•œ ์š”์†Œ์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธ

if (menu.stream().anyMatch(Dish::isVegetarian)) {
            System.out.println("This menu is vegetarian");
        }

anyMatch๋Š” ๋ถˆ๋ฆฌ์–ธ์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ ์ตœ์ข…์—ฐ์‚ฐ์ด๋‹ค.

allMatch

ํ”„๋ ˆ๋””์ผ€์ดํŠธ๊ฐ€ ๋ชจ๋“  ์š”์†Œ์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌ

boolean isHealty = menu.stream().allMatch(dish -> dish.getCalories() < 1000);

noneMatch

noneMatch๋Š” allMatch์™€ ๋ฐ˜๋Œ€ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

boolean isHealty = menu.stream().noneMatch(dish -> dish.getCalories() >= 1000);

anyMatch, allMatch, noneMatch ์„ธ ๋ฉ”์„œ๋“œ๋Š” ์ŠคํŠธ๋ฆผ ์‡ผํŠธ ์„œํ‚ท๊ธฐ๋ฒ•, ์ฆ‰ ์ž๋ฐ”์˜ && || ์™€ ๊ฐ™์€ ์—ฐ์‚ฐ์„ ํ™œ์šฉํ•œ๋‹ค.

์š”์†Œ ๊ฒ€์ƒ‰

์š”์†Œ ๊ฒ€์ƒ‰ ๋ฉ”์„œ๋“œ๋“ค์„ ์‚ดํŽด๋ณด๊ธฐ ์ „์— Optional๋ถ€ํ„ฐ ์•Œ์•„๋ณด๊ฒ ๋‹ค.
Optional ํด๋ž˜์Šค๋Š” ๊ฐ’์˜ ์กด์žฌ๋‚˜ ๋ถ€์žฌ ์—ฌ๋ถ€๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ ํด๋ž˜์Šค์ด๋‹ค. Optional์€ ๊ฐ’์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•˜๊ณ  ๊ฐ’์ด ์—†์„ ๋•Œ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ์ง€ ๊ฐ•์ œํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•œ๋‹ค.
isPresent(), ifPresent, T get(), T orElse(T other)

menu.stream().filter(Dish::isVegetarian).findAny().ifPresent(dish -> System.out.println(dish.getName());

findAny

findAny ๋ฉ”์„œ๋“œ๋Š” ํ˜„์žฌ ์ŠคํŠธ๋ฆผ์—์„œ ์ž„์˜์˜ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

Optional<Dish> dish = menu.stream().filter(Dish::isVegetarian).findAny();

findFirst

์ŠคํŠธ๋ฆผ์€ ๋ฆฌ์ŠคํŠธ์˜ ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ๋„๋ก findFirst ๋ฉ”์„œ๋“œ๋ฅผ ์ง€์›ํ•œ๋‹ค.

List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstSquareDivisibleByThree = somNumbers.stream().map(n -> n * n).filter(n -> n % 3 == 0).findFirst(); //9

์œ„์˜ ์ฝ”๋“œ๋Š” ์ˆซ์ž ๋ฆฌ์ŠคํŠธ์—์„œ 3์œผ๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€๋Š” ์ฒซ ๋ฒˆ์งธ ์ œ๊ณฑ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ฝ”๋“œ์ด๋‹ค.

reduce

reduce๋Š” ์ŠคํŠธ๋ฆผ์—์„œ ๋ˆ„์ ๊ฐ’์„ ์—ฐ์‚ฐํ•˜๋Š” ๋ฉ”์„œ๋“œ์ด๋‹ค. reduce๋ฅผ ์ด์šฉํ•˜์—ฌ sum, max, min ๋“ฑ ๋‹ค์–‘ํ•œ ์—ฐ์‚ฐ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
๋˜ํ•œ ์ดˆ๊ธฐ๊ฐ’์˜ ์œ ๋ฌด์— ๋”ฐ๋ผ Optional๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€๊ฐ€ ๊ฒฐ์ •๋œ๋‹ค.
์•„๋ž˜๋Š” reduce๋กœ ๊ตฌํ˜„ํ•œ sum, max, min์˜ ์˜ˆ์ œ์ด๋‹ค.

Optional<Integer> sum = numbers.stream().reduce(Integer::sum);
Optional<Integer> max = numbers.stream().reduce(Integer::max);
Optional<Integer> min = numbers.stream().reduce(Integer::min);

์ˆซ์žํ˜• ์ŠคํŠธ๋ฆผ

์ŠคํŠธ๋ฆผ์€ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ธฐ๋ณธํ˜• ํŠนํ™” ์ŠคํŠธ๋ฆผ์„ ์ง€์›ํ•œ๋‹ค.
IntStream, DoubleStream, LongStream์ด ๊ทธ ์˜ˆ์ด๋‹ค.

์•ž์„  ์˜ˆ์ œ์ธ menu.stream().map(Dish::getCalories).reduce(0, Integer::sum)์—์„œ ์‚ฌ์‹ค ๋ฐ•์‹ฑ ๋น„์šฉ์ด ์ˆจ์–ด์žˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ ํ•ฉ๊ณ„๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ์ „ Integer๋ฅผ ๊ธฐ๋ณธํ˜•์œผ๋กœ ์–ธ๋ฐ•์‹ฑํ•ด์•ผํ•œ๋‹ค. ์ด๋Ÿฐ์ ์„ ํšจ์œจ์ ์œผ๋กœ ํ•˜๊ธฐ ์œ„ํ•ด ๊ธฐ๋ณธํ˜• ํŠนํ™” ์ŠคํŠธ๋ฆผ์„ ์ง€์›ํ•œ๋‹ค.

์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ

๊ฐ’์œผ๋กœ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ

์ž„์˜์˜ ์ˆ˜๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š” ์ •์  ๋ฉ”์„œ๋“œ Stream.of๋ฅผ ์ด์šฉํ•ด์„œ ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

Stream<String> stream = Stream.of("Modern", "Java", "In", "Action");

๋˜ํ•œ ๋‹ค์Œ์ฒ˜๋Ÿผ empty ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ŠคํŠธ๋ฆผ์„ ๋น„์šธ ์ˆ˜ ์žˆ๋‹ค.

Stream<String> emptyStream = Stream.empty();

null์ด ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด๋กœ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ

์ž๋ฐ” 9์—์„œ๋Š” null์ด ๋  ์ˆ˜ ์žˆ๋Š” ๊ฐœ์ฒด๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ์ƒˆ๋กœ์šด ๋ฉ”์†Œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.

Stream<String> homeValueStream = Stream.ofNullable(System.getProperty("home"));

๋ฐฐ์—ด๋กœ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ

๋ฐฐ์—ด์„ ์ธ์ˆ˜๋กœ ๋ฐ›๋Š” ์ •์  ๋ฉ”์„œ๋“œ Arrays.stream์„ ์ด์šฉํ•ด์„œ ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

int[] numbers = {2, 3, 5, 7, 11, 13};
int sum = Arrays.stream(numbers).sum();

ํŒŒ์ผ๋กœ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ

ํŒŒ์ผ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋“ฑ์˜ I/O ์—ฐ์‚ฐ์— ์‚ฌ์šฉํ•˜๋Š” ์ž๋ฐ”์˜ API๋„ ์ŠคํŠธ๋ฆผ API๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ์—…๋ฐ์ดํŠธ ๋˜์—ˆ๋‹ค.

ํ•จ์ˆ˜๋กœ ๋ฌดํ•œ ์ŠคํŠธ๋ฆผ ๋งŒ๋“ค๊ธฐ

์ŠคํŠธ๋ฆผ API๋Š” ํ•จ์ˆ˜์—์„œ ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๋‘ ์ •์  ๋ฉ”์„œ๋“œ Stream.iterate์™€ Stream.generate๋ฅผ ์ œ๊ณตํ•œ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋“ค์„ ์ด์šฉํ•ด์„œ ํฌ๊ธฐ๊ฐ€ ๊ณ ์ •๋˜์ง€ ์•Š์€ ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋ณดํ†ต ๋ฌดํ•œํ•œ ๊ฐ’์„ ์ถœ๋ ฅํ•˜์ง€ ์•Š๋„๋ก limit(n)ํ•จ์ˆ˜๋ฅผ ํ•จ๊ป˜ ์—ฐ๊ฒฐํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค.
iterate ๋ฉ”์„œ๋“œ ์˜ˆ์ œ

Stream.iterate(0, n -> n+ 2).limit(10).forEach(System.out::println);

generate ๋ฉ”์„œ๋“œ ์˜ˆ์ œ

Stream.generate(Math::random).limit(5).forEach(System.out::println);

iterate์™€ generate์˜ ์ฐจ์ด์ ์€ iterate๋Š” ์ƒ์‚ฐ๋œ ๊ฐ’์„ ์—ฐ์†์ ์œผ๋กœ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๊ณ  generate๋Š” ์ƒˆ๋กœ์šด ๊ฐ’์„ ์ƒ์„ฑํ•œ๋‹ค๋Š” ์ฐจ์ด์ ์ด ์žˆ๋‹ค.

๋งˆ์น˜๋ฉฐ

  • ์ŠคํŠธ๋ฆผ API๋ฅผ ์ด์šฉํ•˜๋ฉด ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์งˆ์˜๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • filter, distinct, takeWhile, dropWhile, skip, limit ๋ฉ”์„œ๋“œ๋กœ ์ŠคํŠธ๋ฆผ์„ ํ•„ํ„ฐ๋งํ•˜๊ฑฐ๋‚˜ ์ž๋ฅผ ์ˆ˜ ์žˆ๋‹ค.
  • ์†Œ์Šค๊ฐ€ ์ •๋ ฌ๋˜์–ด ์žˆ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์•Œ๊ณ  ์žˆ์„ ๋•Œ takeWhile๊ณผ dropWhile ๋ฉ”์†Œ๋“œ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.
  • map, flatMap ๋ฉ”์„œ๋“œ๋กœ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋ฅผ ์ถ”์ถœํ•˜๊ฑฐ๋‚˜ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • findFirst, findAny ๋ฉ”์„œ๋“œ๋กœ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋ฅผ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค. allMatch, noneMatch, anyMatch ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด์„œ ์ฃผ์–ด์ง„ ํ”„๋ ˆ๋””์ผ€์ดํŠธ์™€ ์ผ์น˜ํ•˜๋Š” ์š”์†Œ๋ฅผ ์ŠคํŠธ๋ฆผ์—์„œ ๊ฒ€์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋“ค ๋ฉ”์„œ๋“œ๋Š” ์‡ผํŠธ์„œํ‚ท, ์ฆ‰ ๊ฒฐ๊ณผ๋ฅผ ์ฐพ๋Š” ์ฆ‰์‹œ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ, ์ „์ฒด ์ŠคํŠธ๋ฆผ์„ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๋Š”๋‹ค.
  • reduce ๋ฉ”์„œ๋“œ๋กœ ์ŠคํŠธ๋ฆผ์˜ ๋ชจ๋“  ์š”์†Œ๋ฅผ ๋ฐ˜๋ณต ์กฐํ•ฉํ•˜๋ฉฐ ๊ฐ’์„ ๋„์ถœํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด reduce๋กœ ์ตœ๋Œ“๊ฐ’์ด๋‚˜ ๋ชจ๋“  ์š”์†Œ์˜ ํ•ฉ๊ณ„๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ๋‹ค.
  • filter, map๋“ฑ์€ ์ƒํƒœ๋ฅผ ์ €์žฅํ•˜์ง€ ์•Š๋Š” ์ƒํƒœ ์—†๋Š” ์—ฐ์‚ฐ์ด๋‹ค. reduce๊ฐ™์€ ์—ฐ์‚ฐ์€ ๊ฐ’์„ ๊ณ„์‚ฐํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ์ƒํƒœ๋ฅผ ์ €์žฅํ•œ๋‹ค. sorted, distinct ๋“ฑ์˜ ๋ฉ”์„œ๋“œ๋Š” ์ƒˆ๋กœ์šด ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ์— ์•ž์„œ ์ŠคํŠธ๋ฆผ์˜ ๋ชจ๋“  ์š”์†Œ๋ฅผ ๋ฒ„ํผ์— ์ €์žฅํ•ด์•ผํ•œ๋‹ค. ์ด๋Ÿฐ ๋ฉ”์„œ๋“œ๋ฅผ ์ƒํƒœ ์žˆ๋Š” ์—ฐ์‚ฐ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.
  • IntStream, DoubleStream, LongStream์€ ๊ธฐ๋ณธํ˜• ํŠนํ™” ์ŠคํŠธ๋ฆผ์ด๋‹ค. ์ด๋“ค ์—ฐ์‚ฐ์€ ๊ฐ๊ฐ์˜ ๊ธฐ๋ณธํ˜•์— ๋งž๊ฒŒ ํŠนํ™”๋˜์–ด ์žˆ๋‹ค.
  • ์ปฌ๋ ‰์…˜๋ฟ ์•„๋‹ˆ๋ผ ๊ฐ’, ๋ฐฐ์—ด, ํŒŒ์ผ, iterate์™€ generate ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋กœ๋„ ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฌดํ•œํ•œ ๊ฐœ์ˆ˜์˜ ์š”์†Œ๋ฅผ ๊ฐ€์ง„ ์ŠคํŠธ๋ฆผ์„ ๋ฌดํ•œ ์ŠคํŠธ๋ฆผ์ด๋ผ ํ•œ๋‹ค.

Chapter 2. ๋™์ž‘ ํŒŒ๋ผ๋ฏธํ„ฐํ™” ์ฝ”๋“œ ์ „๋‹ฌํ•˜๊ธฐ

๋™์  ํŒŒ๋ผ๋ฏธํ„ฐํ™”

์ž์ฃผ ๋ฐ”๋€Œ๋Š” ์š”๊ตฌ์‚ฌํ•ญ

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

๋™์  ํŒŒ๋ผ๋ฏธํ„ฐํ™”์˜ ์žฅ์ 

  • ๋ฆฌ์ŠคํŠธ์˜ ๋ชจ๋“  ์š”์†Œ์— ๋Œ€ํ•ด์„œ '์–ด๋–ค ๋™์ž‘'์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ
  • ๋ฆฌ์ŠคํŠธ ๊ด€๋ จ ์ž‘์—…์„ ๋๋‚ธ ๋‹ค์Œ์— '์–ด๋–ค ๋‹ค๋ฅธ ๋™์ž‘'์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ
  • ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด '์ •ํ•ด์ง„ ์–ด๋–ค ๋‹ค๋ฅธ ๋™์ž‘'์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ

๋ณ€ํ™”ํ•˜๋Š” ์š”๊ตฌ์‚ฌํ•ญ์— ๋Œ€์‘ํ•˜๊ธฐ (์‚ฌ๊ณผ)

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

์ฒซ ๋ฒˆ์งธ ์‹œ๋„ : ๋…น์ƒ‰ ์‚ฌ๊ณผ ํ•„ํ„ฐ๋ง

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;
    }

๋‹ค์Œ ์ฝ”๋“œ๋Š” ์‚ฌ๊ณผ ๋ฆฌ์ŠคํŠธ ์ค‘ ๋…น์ƒ‰ ์‚ฌ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์†Œ๋“œ์ด๋‹ค. ์—ฌ๊ธฐ์„œ ๋†๋ถ€๋Š” ๋…น์ƒ‰ ์‚ฌ๊ณผ ์ด์™ธ์—๋„ ๋นจ๊ฐ„ ์‚ฌ๊ณผ ๋˜ํ•œ ํ•„ํ„ฐ๋งํ•˜๊ณ  ์‹ถ์–ด์กŒ๋‹ค. ๋ฉ”์†Œ๋“œ๋ฅผ ๋ณต์‚ฌํ•˜์—ฌ GREEN์„ RED๋กœ ๋ฐ”๊พธ๋Š” ๋ฐฉ๋ฒ• ๋“ฑ ์—ฌ๋Ÿฌ ๋ฐฉ๋ฒ•์ด ์žˆ์ง€๋งŒ ์ƒ‰์ด ์ถ”๊ฐ€๋˜๋ฉด ์ ์ ˆํ•˜๊ฒŒ ๋Œ€์‘ํ•  ์ˆ˜ ์—†๋‹ค. ์ด๋Ÿฐ ์ƒํ™ฉ์—์„œ๋Š” ๋ฐ˜๋ณต๋˜๋Š” ๋ถ€๋ถ„์„ ์ถ”์ƒํ™” ํ•ด์ค€๋‹ค.

๋‘ ๋ฒˆ์งธ ์‹œ๋„ : ์ƒ‰์„ ํŒŒ๋ผ๋ฏธํ„ฐํ™”

public static List<Apple> filterApplesByColor(List<Apple> inventory, Color color) {
        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(apple.getColor().equals(color)){
                result.add(apple);
            }
        }
        return result;
    }

๋‘ ๋ฒˆ์งธ ์ฝ”๋“œ๋Š” ๋ณด๋‹ค์‹ถ์ด ์ƒ‰๊น”์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ๋ฐ›์•„ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์ƒ‰๊น”์— ๋งž์ถ”์–ด ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ๋†๋ถ€๊ฐ€ ์ƒ‰ ์ด์™ธ์—๋„ ๋ฌด๊ฒŒ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ํ•„ํ„ฐ๋งํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋ฌด๊ฒŒ ์ •๋ณด ๋˜ํ•œ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ถ”๊ฐ€ํ•ด์•ผํ•œ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๊ธฐ์กด์— Color๋กœ ํ•„ํ„ฐ๋งํ•˜๋Š” ํ•จ์ˆ˜์™€ ์ค‘๋ณต๋˜๋Š” ๋‹จ์ ์ด ์žˆ๋‹ค.

์„ธ ๋ฒˆ์งธ ์‹œ๋„ : ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์†์„ฑ์œผ๋กœ ํ•„ํ„ฐ๋ง

public static List<Apple> filterApples(List<Apple> inventory, Color color, int weight, boolean flag) {
        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if((flag && apple.getColor().equals(color)) ||
                    (!flag && apple.getWeight() > weight))
                result.add(apple);
            }
        }
        return result;
    }

์„ธ ๋ฒˆ์งธ ์‹œ๋„๋Š” ๋ชจ๋“  ์†์„ฑ์„ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜๊ฒจ์ฃผ๊ณ  flag๋กœ ๊ตฌ๋ถ„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ์ด ๋ฐฉ๋ฒ•์€ ์–ผ๋งˆ ๊ณต๋ถ€ํ•˜์ง€ ์•Š์€ ๋‚ด๊ฐ€ ๋ด๋„ ์ตœ์•…์˜ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ƒ๊ฐ์ด ๋œ๋‹ค. ๋ฌด์—‡์„ ๋‚˜ํƒ€๋‚ด๋Š” ๊ฒƒ์ธ์ง€ ์•Œ ์ˆ˜ ์—†๋Š” flag, ๋„ˆ๋ฌด ๋งŽ์€ ํŒŒ๋ผ๋ฏธํ„ฐ, ๋˜ํ•œ ์š”๊ตฌ์‚ฌํ•ญ์ด ์ถ”๊ฐ€๋˜๋ฉด ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ๋” ๊ธธ์–ด์ง€๊ฒŒ ๋  ๊ฒƒ์ด๊ณ  ์ด๋Š” ๊ฐ€๋…์„ฑ์„ ๋–จ์–ด๋œจ๋ฆฐ๋‹ค.

๋„ค ๋ฒˆ์งธ ์‹œ๋„ : ์ถ”์ƒ์  ์กฐ๊ฑด์œผ๋กœ ํ•„ํ„ฐ๋ง

public static List<Apple> filterApples(List<Apple> inventory, ApplePredicate p) {
        List<Apple> result = new ArrayList<>();
        for(Apple apple: inventory){
            if(p.test(apple)){
                result.add(apple);
            }
        }
        return result;
    }

์ด๋ฒˆ์—๋Š” ์ „๋žต ๋””์ž์ธํŒจํ„ด(strategy design pattern)์„ ์‚ฌ์šฉํ•œ implements๋ฅผ ํ†ตํ•ด ์•ž์„  ์ฝ”๋“œ๋ณด๋‹ค ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์„ ์ฐพ์•„๋‚ด์—ˆ๋‹ค. ApplePredicate๊ฐ์ฒด๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐํ™”ํ•˜์—ฌ ๋‚ด๋ถ€์ ์œผ๋กœ ๋‹ค์–‘ํ•œ ๋™์ž‘์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์ด๋‹ค. ๋‹ค๋ฅธ ์š”๊ตฌ์‚ฌํ•ญ์ด ์ถ”๊ฐ€๋˜๋ฉด ์šฐ๋ฆฌ๋Š” ApplePredicate๋ฅผ implements ๋ฐ›๋Š” ํด๋ž˜์Šค๋ฅผ ๊ตฌํ˜„ํ•˜์—ฌ ์š”๊ตฌ์‚ฌํ•ญ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ณต์žกํ•œ ๊ณผ์ • ๊ฐ„์†Œํ™”

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

๋‹ค์„ฏ ๋ฒˆ์งธ ์‹œ๋„ : ์ต๋ช… ํด๋ž˜์Šค ์‚ฌ์šฉ

List<Apple> redApples = filterApples(inventory, new ApplePredicate() {
            public boolean test(Apple apple){
                return RED.equals(apple.getColor());
            }
        });

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

์—ฌ์„ฏ ๋ฒˆ์งธ ์‹œ๋„ : ๋žŒ๋‹ค ํ‘œํ˜„์‹ ์‚ฌ์šฉ

List<Apple> result = filterApples(inventry, (Apple apple) -> RED.equals(apple.getColor()));

์ด๋ฒˆ ๋ชจ๋˜ ์ธ ์•ก์…˜ ์ž๋ฐ”์—์„œ ๋งŽ์ด ๋‹ค๋ฃฐ ์ž๋ฐ” 8, 9, 10 ์ค‘ ์ž๋ฐ” 8์—์„œ ๋“ฑ์žฅํ•œ ๋žŒ๋‹ค ํ‘œํ˜„์‹์„ ์‚ฌ์šฉํ•˜์˜€๋‹ค. ์•ž์—์„œ ์šฐ๋ฆฌ๊ฐ€ ์ง€๋‚˜์˜จ ์ฝ”๋“œ๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๋‹จํ•ด์ ธ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.