๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿ“– Java&Spring/๋ชจ๋˜์ž๋ฐ”์ธ์•ก์…˜

[๋ชจ๋˜์ž๋ฐ”์ธ์•ก์…˜] Stream ์ŠคํŠธ๋ฆผ ํ™œ์šฉ

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

๋ช…์‹œ์  ๋ฐ˜๋ณต ๋Œ€์‹  filter์™€ collect ์—ฐ์‚ฐ์„ ์ง€์›ํ•˜๋Š” ์ŠคํŠธ๋ฆผ API๋ฅผ ์ด์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ ์ปฌ๋ ‰์…˜ ๋ฐ˜๋ณต์„ ๋‚ด๋ถ€์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

    @Test
    void streamSample() {
        List<String> nameList = new ArrayList<>();
        nameList.add("๋Ÿญ์Šค");
        nameList.add("๋ฃฐ๋ฃจ");
        nameList.add("์• ์‰ฌ");
        nameList.add("ํŠธ๋ฆฐ๋‹ค๋ฏธ์–ด");

        // ์™ธ๋ถ€ ๋ฐ˜๋ณต
        List<String> longNameList = new ArrayList<>();
        for (String s : nameList) {
            if(s.length() > 5) {
                longNameList.add(s);
            }
        }
        // ๋‚ด๋ถ€ ๋ฐ˜๋ณต
        List<String> longNameStreamList = nameList.stream()
                .filter(s -> s.length() >5)
                .collect(Collectors.toList());
    }

 

์ŠคํŠธ๋ฆผ API๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ ์–ด๋–ป๊ฒŒ ์ฒ˜๋ฆฌํ• ์ง€ ๊ด€๋ฆฌํ•ด์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ์ดํ„ฐ๋ฅผ ํŽธํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค์–‘ํ•œ ์ตœ์ ํ™”๊ฐ€ ์ด๋ฃจ์–ด์ง€๊ณ , ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ• ์ง€ ์—ฌ๋ถ€๋„ ๊ฒฐ์ •ํ•ด์ค€๋‹ค.

์ˆœ์ฐจ์ ์ธ ๋ฐ˜๋ณต์„ ๋‹จ์ผ ์Šค๋ ˆ๋“œ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ์™ธ๋ถ€ ๋ฐ˜๋ณต์€ ์ด๋ฅผ ํ•  ์ˆ˜ ์—†์œผ์…ˆ.

 

ํ•„ํ„ฐ๋ง

ํ•„ํ„ฐ๋ง์€ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋ฅผ ์„ ํƒํ•˜๋Š” ๋ฐฉ๋ฒ•์ธ Predicate ํ•„ํ„ฐ๋ง ๋ฐฉ๋ฒ•๊ณผ ๊ณ ์œ  ์š”์†Œ๋งŒ ํ•„ํ„ฐ๋ง ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค.

Predicate๋ฅผ ์ด์šฉํ•œ ํ•„ํ„ฐ๋ง

    // Dish ํด๋ž˜์Šค์˜ Predicate ๋ฉ”์„œ๋“œ
         public boolean isVegetarian() {
            return vegetarian;
        }

   @Test
    @DisplayName("Predicate filtering")
    void predicateFilter() {
        List<Dish> vegetarianMenu = menuList.stream()
                .filter(Dish::isVegetarian) // Predicate
                .collect(Collectors.toList());
    }

 

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

 

๊ณ ์œ  ์š”์†Œ ํ•„ํ„ฐ๋ง

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

์ŠคํŠธ๋ฆผ์—์„œ ๊ฐ์ฒด๋“ค์˜ ๊ณ ์œ ์„ฑ์„ ํŒ๋‹จํ•  ๋•Œ, ํ•ด๋‹น ๊ฐ์ฒด๋“ค์˜ hashCode์™€ equals ๋ฉ”์„œ๋“œ๊ฐ€ ํ˜ธ์ถœํ•œ๋‹ค.

hashCode์™€ equals ๋ฉ”์„œ๋“œ

Java ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ๊ฐ์ฒด์˜ ๊ณ ์œ ์„ฑ์„ ๊ฒฐ์ •ํ•  ๋•Œ, hashCode ๋ฉ”์„œ๋“œ์™€ equals ๋ฉ”์„œ๋“œ๊ฐ€ ์‚ฌ์šฉ๋œ๋‹ค

 

  1. hashCode ๋ฉ”์„œ๋“œ:
    • hashCode ๋ฉ”์„œ๋“œ๋Š” ๊ฐ์ฒด์˜ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํ•ด์‹œ ์ฝ”๋“œ๋Š” ๊ฐ์ฒด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ •์ˆ˜ ๊ฐ’์ด๋ฉฐ, ์ผ๋ฐ˜์ ์œผ๋กœ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ์ฒด์— ๋Œ€ํ•ด ์„œ๋กœ ๋‹ค๋ฅธ ํ•ด์‹œ ์ฝ”๋“œ๊ฐ€ ๋ฐ˜ํ™˜๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‘ ๊ฐœ์˜ ๋‹ค๋ฅธ ๊ฐ์ฒด๊ฐ€ ๊ฐ™์€ ํ•ด์‹œ ์ฝ”๋“œ๋ฅผ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•ด์‹œ ์ฝ”๋“œ๋Š” ๊ฐ์ฒด๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ฐ ์™„์ „ํžˆ ์‹ ๋ขฐํ•  ์ˆ˜ ์žˆ๋Š” ์ˆ˜๋‹จ์€ ์•„๋‹™๋‹ˆ๋‹ค.
  2. equals ๋ฉ”์„œ๋“œ:
    • equals ๋ฉ”์„œ๋“œ๋Š” ๋‘ ๊ฐ์ฒด๊ฐ€ ๋™๋“ฑํ•œ์ง€ ์—ฌ๋ถ€๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋‘ ๊ฐ์ฒด๊ฐ€ ์„œ๋กœ ๊ฐ™์€ ๋‚ด์šฉ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€๋ฅผ ํŒ๋‹จํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ฉ”์„œ๋“œ๋ฅผ ์ ์ ˆํžˆ ์žฌ์ •์˜ํ•˜์—ฌ ๊ฐ์ฒด ๊ฐ„์˜ ๋‚ด์šฉ์ ์ธ ๋น„๊ต๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ์ด ๋‘ ๋ฉ”์„œ๋“œ๋Š” ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋ฉฐ, ๊ฐ์ฒด๊ฐ€ ๊ฐ™์€์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, Java์˜ ์ปฌ๋ ‰์…˜ ํ”„๋ ˆ์ž„์›Œํฌ์—์„œ ๊ฐ์ฒด๋ฅผ ์ €์žฅํ•˜๊ฑฐ๋‚˜ ๊ฒ€์ƒ‰ํ•  ๋•Œ, hashCode์™€ equals๊ฐ€ ์ œ๋Œ€๋กœ ๊ตฌํ˜„๋˜์ง€ ์•Š์œผ๋ฉด ์›ํ•˜๋Š” ๋™์ž‘์„ ์–ป์„ ์ˆ˜ ์—†์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ž๋ฐ”์—์„œ๋Š” hashCode์™€ equals๋ฅผ ์ ์ ˆํžˆ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜์—ฌ ๊ฐ์ฒด์˜ ๋™๋“ฑ์„ฑ(equality)์„ ์ •์˜ํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๋งŒ์•ฝ ์ด๋ฅผ ์ œ๋Œ€๋กœ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š์œผ๋ฉด ๊ฐ์ฒด์˜ ๋™๋“ฑ์„ฑ์„ ๊ฒ€์‚ฌํ•˜๋Š”๋ฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„๋ฌดํŠผ.. distinct ๋‹จ์–ด ๋œป์ฒ˜๋Ÿผ, ๋ฐ์ดํ„ฐ์˜ ์š”์†Œ์—์„œ ์ค‘๋ณต์„ ํ•„ํ„ฐ๋ง ํ•ฉ๋‹ˆ๋‹ค.

 

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

Predicate๋ฅผ ์ด์šฉํ•œ ์Šฌ๋ผ์ด์‹ฑ

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

takeWhile

    @Test
    @DisplayName("takeWhile")
    void takeWhileTest() {
        // 100 ์นผ๋กœ๋ฆฌ ์ดํ•˜ ์š”๋ฆฌ ์„ ํƒํ•˜๊ธฐ ์œ„ํ•ด filter() ์‚ฌ์šฉ
        List<Dish> filteredMenu = menuList.stream()
                .filter(dish -> dish.getCalories() < 100)
                .collect(Collectors.toList());

    }

 

๋งŒ์•ฝ 100 ์นผ๋กœ๋ฆฌ ์ดํ•˜์ธ ์š”๋ฆฌ๋ฅผ ์„ ํƒํ•˜๋ ค๋ฉด ์œ„์™€ ๊ฐ™์ด filter ํ•จ์ˆ˜๋ฅผ ์จ์„œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

filter ์—ฐ์‚ฐ์„ ์ด์šฉํ•˜๋ฉด ์ „์ฒด ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜๋ณตํ•˜๋ฉด์„œ ๊ฐ ์š”์†Œ์— Predicate๋ฅผ ์ ์šฉํ•˜๊ฒŒ ๋œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ์นผ๋กœ๋ฆฌ ์ˆœ์œผ๋กœ ์ด๋ฏธ ์ •๋ ฌ์ด ๋˜์–ด์žˆ์Œ.

์ด๋ฏธ ๋ฆฌ์ŠคํŠธ๊ฐ€ ์นผ๋กœ๋ฆฌ ์ˆœ์œผ๋กœ ์ •๋ ฌ๋˜์–ด์žˆ๋‹ค๋ฉด ๋˜‘๊ฐ™์€ Predicate๋ฅผ ๋ฐ˜๋ณตํ•  ํ•„์š”๋Š” ์—†๋Š” ๊ฒƒ์ž„.

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

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ๊ฒŒ takeWhile์ด๋ž€ ๋ง์”€.

    .stream()
    .takeWhile(dish -> dish.getCaloried() < 100)

dropWhile

๊ทธ๋Ÿฌ๋ฉด ๋งŒ์•ฝ 100 ์นผ๋กœ๋ฆฌ๋ณด๋‹ค ํฐ ์š”๋ฆฌ๋ฅผ ํƒ์ƒ‰ํ•˜๋ ค๋ฉด? dropWhile์„ ์ด์šฉํ•ด์„œ ํ•  ์ˆ˜ ์žˆ๋‹ค.

.stream()
.dropWhile(dish -> dish.getCalories() < 100)

 

takeWhile๊ณผ ์ •๋ฐ˜๋Œ€์˜ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•จ. Predicate๊ฐ€ ์ฒ˜์Œ์œผ๋กœ ๊ฑฐ์ง“์ด๋˜๋Š” ์ง€์ ๊นŒ์ง€ ๋ฐœ๊ฒฌ๋˜๋Š” ์š”์†Œ๋“ค์„ ๋ฒ„๋ ค์ค€๋‹ค.

๋ฌดํ•œํ•œ ๋‚จ์€ ์š”์†Œ๋ฅผ ๊ฐ€์ง„ ๋ฌดํ•œ ์ŠคํŠธ๋ฆผ์—์„œ๋„ ๋™์ž‘ํ•œ๋‹ค๊ณ  ํ•จ.

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

๊ฐ’์„ ํ•„ํ„ฐ๋ง ํ–ˆ๋‹ค๋ฉด, ์š”์†Œ์˜ ๊ฐœ์ˆ˜์—๋„ ์ œํ•œ์„ ๊ฑธ ์ˆ˜ ์žˆ๋‹ค. limit(n) ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.

์ŠคํŠธ๋ฆผ์ด ์ •๋ ฌ๋˜์–ด์žˆ๋‹ค๋ฉด ์ตœ๋Œ€ ์š”์†Œ n๊ฐœ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

    List<Dish> limit3Menu = menuList.stream()
                .filter(dish -> dish.getCalories() < 100)
                .limit(2)
                .collect(Collectors.toList());

์ŠคํŠธ๋ฆผ ์š”์†Œ ๊ฑด๋„ˆ๋›ฐ๊ธฐ

limit๋„ ๊ทธ๋ ‡๊ณ  skip๋„ filter ๊ฐ™์€ ๋‹ค๋ฅธ ์—ฐ์‚ฐ๊ณผ ์ƒํ˜ธ ๋ณด์™„์ ์ธ ์—ฐ์‚ฐ์„ ์ˆ˜ํ–‰ํ•ด์ค€๋‹ค.

    List<Dish> skip2Menu = menuList.stream()
                .filter(dish -> dish.getCalories() < 100)
                .skip(2)
                .collect(Collectors.toList());

 

Mapping

์ŠคํŠธ๋ฆผ์—์„œ๋Š” ํŠน์ • ๋ฐ์ดํ„ฐ๋ฅผ ์„ ํƒํ•˜๋Š” ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์—ฐ์‚ฐ์ธ map๊ณผ flatMap์„ ์ง€์›ํ•œ๋‹ค.

 

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

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

๊ธฐ์กด์˜ ๊ฐ’์„ ์ƒˆ๋กœ์šด ๋ฒ„์ „์œผ๋กœ ๋งŒ๋“œ๋Š” ๊ฐœ๋…์ด๋‹ค.

    @Test
    @DisplayName("Mapping")
    void mappingTest() {
        List<String> dishNameList = menuList.stream()
                .map(Dish::getName)
                .collect(Collectors.toList());
    }

 

์š”๋ฆฌ์˜ ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ค๋Š” getName์„ ์‚ฌ์šฉํ•˜์—ฌ ์ŠคํŠธ๋ฆผ์„ ์ƒ์„ฑํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์—, ์ถœ๋ ฅ ์ŠคํŠธ๋ฆผ์€ Stream ํ˜•์‹์ด๋‹ค.

 

        List<Integer> dishNameLengthList = dishNameList.stream()
                .map(String::length)
                .collect(Collectors.toList());

 

์š”๋ฆฌ์˜ ์ด๋ฆ„์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฆฌ์ŠคํŠธ๋„ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

์š”๋ฆฌ์˜ ์ด๋ฆ„์„ ์ธ์ˆ˜๋กœ ๋ฐ›์•„์„œ, ๋ฌธ์ž์—ด์˜ ๊ธธ์ด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” String::length๋ฅผ map ๋ฉ”์„œ๋“œ์— ์ „๋‹ฌํ•˜๋ฉด ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

List<Integer> dishNameLengthList = menuList.stream()
                .map(Dish::getName)
                .map(String::length)
                .collect(Collectors.toList());

 

์š”๋ฆฌ ๋ฆฌ์ŠคํŠธ์—์„œ ํ•œ๋ฒˆ์— ์š”๋ฆฌ์˜ ์ด๋ฆ„์˜ ๊ธธ์ด ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜๋„ ์žˆ๋‹ค.

์ด๋ฅผ Chaining์ด๋ผ๊ณ  ํ•œ๋‹ค.

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

๋ฆฌ์ŠคํŠธ๋กœ ์–ป์–ด์˜จ ๋ฌธ์ž์—ด์„ ์ชผ๊ฐœ์„œ ๊ณ ์œ  ๋ฌธ์ž๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋ฐ˜ํ™˜๋˜๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค.

    @Test
    @DisplayName("์ค‘๋ณต๋œ ๋ฌธ์ž๊ฐ€ ์ œ๊ฑฐ๋œ ๋ฌธ์ž์—ด ๋ฆฌ์ŠคํŠธ")
    void splitWordsTest() {
        List<String> words = Arrays.asList("apple", "peach", "banana");

        List<String> wordList = words.stream()
                .map(word -> word.split(""))
                .distinct()
                .collect(Collectors.toList());

        System.out.println(wordList);
    } 

 

Stream ํ˜•์‹์„ ๊ฐ–๋Š” ์ŠคํŠธ๋ฆผ์„ ๊ธฐ๋Œ€ํ–ˆ์ง€๋งŒ.. ์•„์‰ฝ๊ฒŒ๋„ ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค.

 

ํƒ€์ž… ๋ณ€์ˆ˜์˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ์—†์œผ๋ฏ€๋กœ String[]์ด(๊ฐ€) String์„(๋ฅผ) ์ค€์ˆ˜ํ•ฉ๋‹ˆ๋‹ค ์ถ”๋ก  ๋ณ€์ˆ˜ T์— ํ˜ธํ™˜๋˜์ง€ ์•Š๋Š” ๋ฐ”์šด๋“œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. equality constraints: String lower bounds: String[]

 

 

์œ„์™€ ๊ฐ™์ด ํ•˜์˜€์„ ๊ฒฝ์šฐ์—๋Š” Stream<String[]> ํ˜•์‹์œผ๋กœ ๋ฐ˜ํ™˜๋˜๋Š” ๊ฒƒ์ด๋‹ค.

split์ด ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

 

@NotNull  
@Contract(pure = true)  
public String[] split(@NotNull  String regex, int limit )

 

 

ํ•˜์ง€๋งŒ Stream์„ ์›ํ•œ๋‹ค๊ตฌ...! ์ด๋Ÿด ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด flatMap ๋ฉ”์„œ๋“œ์ด๋‹ค.

๋งŒ์•ฝ ์œ„์˜ ์˜ˆ์ œ๋ฅผ Stream<String[]>๋กœ ๋ณ€๊ฒฝํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๊ฒฐ๊ณผ๊ฐ€ ์ถœ๋ ฅ๋œ๋‹ค. 

 

[[Ljava.lang.String;@7fb95505, [Ljava.lang.String;@58be6e8, [Ljava.lang.String;@7331196b]

 

map๊ณผ Arrays.stream

flatMap์„ ์‚ฌ์šฉํ•˜๊ธฐ ์ „์—, ๋ฐฐ์—ด ์ŠคํŠธ๋ฆผ ๋Œ€์‹ ์— ๋ฌธ์ž์—ด ์ŠคํŠธ๋ฆผ์„ ๋ด๋ณด์ž.

 

        /**
         String[] words = {"apple", "peach"};
         Stream<String> stream = Arrays.stream(words);
         */

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

 

Arrays::stream์„ ์‚ฌ์šฉํ•ด์„œ ๋ฌธ์ž์—ด์„ ๋ฐ›์•„ ์ŠคํŠธ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜๋Š” ์žˆ์ง€๋งŒ, ์ŠคํŠธ๋ฆผ ๋ฆฌ์ŠคํŠธ๊ฐ€ ๋งŒ๋“ค์–ด์กŒ๊ธฐ ๋•Œ๋ฌธ์— ์›๋ž˜ ๋ชฉํ‘œ์ธ Stream์€ ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š์•˜๋‹ค.

๊ฐ ๋‹จ์–ด๋ฅผ ๊ฐœ๋ณ„ ๋ฌธ์ž์—ด๋กœ ์ด๋ฃจ์–ด์ง„ ๋ฐฐ์—ด๋กœ ๋งŒ๋“  ๋‹ค์Œ์—, ๊ฐ ๋ฐฐ์—ด์„ ๋ณ„๋„์˜ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋งŒ๋“ค์–ด์•ผํ•œ๋‹ค.

 

        List<String> wordStrings = words.stream()
                .map(word -> word.split(""))
                .flatMap(Arrays::stream)
                .distinct()
                .collect(Collectors.toList());
//[a, p, l, e, c, h, b, n]

 

์ด๋ ‡๊ฒŒ ๋ง์ด๋‹ค.

flatMap์€ ๊ฐ ๋ฐฐ์—ด์„ ์ŠคํŠธ๋ฆผ์ด ์•„๋‹ˆ๋ผ, ์ŠคํŠธ๋ฆผ์˜ ์ฝ˜ํ…์ธ ๋กœ ๋งตํ•‘ํ•ด์ค€๋‹ค.

์ด๋ฆ„์ฒ˜๋Ÿผ flatํ•˜๊ฒŒ~ ํ‰๋ฉดํ™”๋œ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•ด์ค€๋‹ค.

 

์ฆ‰, flatMap ๋ฉ”์„œ๋“œ๋Š” ์ŠคํŠธ๋ฆผ์˜ ๊ฐ ๊ฐ’์„ ๋‹ค๋ฅธ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์•Œ์•„์„œ ๋ฐ”๊พธ๊ณ , ๋ชจ๋“  ์ŠคํŠธ๋ฆผ์„ ํ•˜๋‚˜์˜ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์—ฐ๊ฒฐ๊นŒ์ง€ ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๋‹ค...

 

์˜ˆ์ œ

flatMap ์˜ˆ์ œ๊ฐ€ ๋งˆ์Œ์— ๋“ค์–ด์„œ ์ถ”๊ฐ€๋กœ ์ž‘์„ฑํ•ด๋ณธ๋‹ค.

๋งŒ์•ฝ์— ๋‘ ๊ฐœ์˜ ์ˆซ์ž ๋ฆฌ์ŠคํŠธ๊ฐ€ ์žˆ๋Š”๋ฐ, ๋ชจ๋“  ์ˆซ์ž ์Œ์˜ ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ตฌํ•˜๋Š”๋ฐ ๊ทธ ์ค‘ ์ˆซ์ž ์Œ์˜ ํ•ฉ์ด 3์œผ๋กœ ๋‚˜๋ˆ„์–ด ๋–จ์–ด์ง€๋Š” ์ˆซ์ž ์Œ์„ ๊ตฌํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด?

์ด๋ฅผ ๊ตฌ๋‹ฅ๋‹ค๋ฆฌ c์–ธ์–ด๋กœ ๋งŒ๋“ค๋ฉด ์ด๋ ‡๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

#include <stdio.h>

int main() {
    int numberList1[] = {1, 2, 3};
    int numberList2[] = {3, 4};

    int pairs[6][2];
    int count = 0;

    for (int i = 0; i < sizeof(numberList1) / sizeof(numberList1[0]); i++) {
        for (int j = 0; j < sizeof(numberList2) / sizeof(numberList2[0]); j++) {
            if ((numberList1[i] + numberList2[j]) % 3 == 0) {
                pairs[count][0] = numberList1[i];
                pairs[count][1] = numberList2[j];
                count++;
            }
        }
    }

    // Displaying the pairs
    for (int i = 0; i < count; i++) {
        printf("[%d, %d]\n", pairs[i][0], pairs[i][1]);
    }

    return 0;
}

 

๋„ˆ๋ฌด ์‹ซ์€ ์ด์ค‘ for๋ฌธ.. ๊ฐ€๋…์„ฑ๋„ ์•ˆ ์ข‹๊ณ  ๋‹จ์ˆœํ•œ ์˜ˆ์ œ์ด์ง€๋งŒ i์™€ j๊ฐ€ ํ—ท๊ฐˆ๋ฆด ์ˆ˜ ๋ฐ–์— ์—†๋Š” ๊ทธ๋Ÿฐ... (์ด๋ฆ„์„ ์ž˜ ์ •ํ•˜๋ฉด ๋˜์ง€๋งŒ.. ๊ทธ์น˜๋งŒ..)

์ด๋ฅผ flatMap์„ ์‚ฌ์šฉํ•œ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•ด์„œ ์ž‘์„ฑํ•ด๋ณด๋ฉด ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

 

    @Test
    @DisplayName("์ˆซ์ž ๋ฆฌ์ŠคํŠธ์˜ ๋ชจ๋“  ์ˆซ์ž์˜ ์Œ์—์„œ ํ•ฉ์ด 3์œผ๋กœ ๋‚˜๋ˆ„์–ด์ง€๋Š” ์˜ˆ์ œ")
    void numberListTest() {
        List<Integer> numberList1 = Arrays.asList(1,2,3);
        List<Integer> numberList2 = Arrays.asList(3,4);

        List<int[]> pairs = numberList1.stream()
                .flatMap(i -> numberList2.stream()
                        .filter(j->(i+j) % 3 == 0 )
                        .map(j-> new int[] {i, j}))
                .collect(Collectors.toList());
    }

 

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

์ŠคํŠธ๋ฆผ์€ ํŠน์ • ์†์„ฑ์ด ๋ฐ์ดํ„ฐ ์ง‘ํ•ฉ์— ์žˆ๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒ€์ƒ‰ํ•˜๋Š” ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์—๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

allMatch, anyMatch, noneMatch, findFirst, findAny ๋“ฑ์˜ ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฉ”์„œ๋“œ๊ฐ€ ์žˆ์Œ.

 

๋ฉ”์„œ๋“œ ์‚ดํŽด๋ณด๊ธฐ

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

์ฃผ์–ด์ง„ ์ŠคํŠธ๋ฆผ์—์„œ ์ ์–ด๋„ ํ•œ ์š”์†Œ์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•  ๋•Œ anyMatch ๋ฉ”์„œ๋“œ๋ฅผ ์“ธ ์ˆ˜ ์žˆ๋‹ค.

anyMatch๋Š” boolean์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, if ๋ฌธ์œผ๋กœ ๋น„๊ตํ•  ๋•Œ ์šฉ์ดํ•˜๋‹ค.

 

    @Test
    @DisplayName("anyMatch๋กœ ์ ์–ด๋„ ํ•œ ์š”์†Œ์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ํ™•์ธํ•ด๋ณด๊ธฐ")
    void searchAndMatch() {
        if(menuList.stream().anyMatch(Dish::isVegetarian)) {
            System.out.println("The menu is (somewhat) vegetarian friendly");
        }
    }

 

flatMap ๊ณต๋ถ€ํ•  ๋•Œ ๊ตฌ๋‹ฅ๋‹ค๋ฆฌ C์–ธ์–ด๋กœ ๋ฐ”๊ฟ”๋ณด๋‹ˆ ์ฐธ ์žฌ๋ฐŒ๋”๊ตฐ์š”...?

 

#include <stdio.h>

struct Dish {
    int isVegetarian;
};

int anyMatch(struct Dish *menuList, int size) {
    for (int i = 0; i < size; i++) {
        if (menuList[i].isVegetarian) {
            return 1; // True, at least one element is vegetarian
        }
    }
    return 0; // False, no vegetarian element found
}

int main() {
    struct Dish menuList[] = {
        {1}, // Vegetarian
        {0}, // Non-vegetarian
        {1}, // Vegetarian
    };

    int menuSize = sizeof(menuList) / sizeof(menuList[0]);

    if (anyMatch(menuList, menuSize)) {
        printf("The menu is (somewhat) vegetarian friendly\n");
    }

    return 0;
}

 

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

anyMatch์™€ ๋‹ค๋ฅด๊ฒŒ ์ŠคํŠธ๋ฆผ์˜ ๋ชจ๋“  ์š”์†Œ๊ฐ€ ์ฃผ์–ด์ง„ Predicate์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•œ๋‹ค.

 

    @Test
    @DisplayName("allMatch๋กœ ๋ชจ๋“  ์š”์†Œ๊ฐ€ ์กฐ๊ฑด๊ณผ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๊ธฐ")
    void allMatchTest() {
        if(menuList.stream().allMatch(dish -> dish.getCalories() < 1000)) {
            System.out.println("All menu is healthy");
        }
    }

 

noneMatch: ์ฃผ์–ด์ง„ Predicate์™€ ์ผ์น˜ํ•˜๋Š” ์š”์†Œ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ

allMatch์™€ ๋ฐ˜๋Œ€์ด๋‹ค. ์–˜๋Š” ๋ชจ๋“  ์š”์†Œ๊ฐ€ ์ฃผ์–ด์ง„ Predicate์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌํ•œ๋‹ค.

์œ„์˜ allMatch๋ฅผ noneMatch๋กœ ๋ฐ”๊ฟ”๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์“ธ ์ˆ˜ ์žˆ๋‹ค.

 

    @Test
    @DisplayName("noneMatch๋กœ ์กฐ๊ฑด๊ณผ ์ผ์น˜ํ•˜๋Š” ์š”์†Œ๊ฐ€ ์—†๋Š”์ง€ ๊ฒ€์‚ฌํ•˜๊ธฐ")
    void noneMatchTest() {
        if(menuList.stream().noneMatch(dish -> dish.getCalories() >= 1000)) {
            System.out.println("All menu is healthy");
        }
    }

 

short-circuit ๊ธฐ๋ฒ• -> ๋”ฐ๋กœ ๋นผ๊ธฐ

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

์‡ผํŠธ์„œํ‚ท(short-circuit)์€ ์ฃผ๋กœ ๋…ผ๋ฆฌ ์—ฐ์‚ฐ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ๊ฐœ๋…์ด๋‹ค.

ํŠน์ • ์กฐ๊ฑด์ด ์ถฉ์กฑ๋˜๋ฉด ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์„ ํ‰๊ฐ€ํ•˜์ง€ ์•Š๊ณ  ์ „์ฒด ํ‘œํ˜„์‹์˜ ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์„ ๋งํ•œ๋‹ค.

์ด๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์˜ ๋…ผ๋ฆฌ ์—ฐ์‚ฐ์ž์—์„œ ์ž์ฃผ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

๊ฐ€์žฅ ํ”ํ•œ ์‡ผํŠธ์„œํ‚ท ๊ธฐ๋ฒ•์€ ๋…ผ๋ฆฌ AND(&&)์™€ OR(||) ์—ฐ์‚ฐ์ž์—์„œ ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

 

  1. ์‡ผํŠธ์„œํ‚ท AND (&&): ๋…ผ๋ฆฌ AND์—์„œ๋Š” ์ฒซ ๋ฒˆ์งธ ์กฐ๊ฑด์ด ๊ฑฐ์ง“์ธ ๊ฒฝ์šฐ ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์„ ํ‰๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ํ•˜๋‚˜๋ผ๋„ ๊ฑฐ์ง“์ด๋ฉด ์ „์ฒด ํ‘œํ˜„์‹์˜ ๊ฒฐ๊ณผ๋Š” ๊ฑฐ์ง“์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.๋งŒ์•ฝ condition1์ด ๊ฑฐ์ง“์ด๋ฉด condition2๋Š” ํ‰๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  2. if (condition1 && condition2) { // code }
  3. ์‡ผํŠธ์„œํ‚ท OR (||): ๋…ผ๋ฆฌ OR์—์„œ๋Š” ์ฒซ ๋ฒˆ์งธ ์กฐ๊ฑด์ด ์ฐธ์ธ ๊ฒฝ์šฐ ๋‚˜๋จธ์ง€ ์กฐ๊ฑด์„ ํ‰๊ฐ€ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ํ•˜๋‚˜๋ผ๋„ ์ฐธ์ด๋ฉด ์ „์ฒด ํ‘œํ˜„์‹์˜ ๊ฒฐ๊ณผ๋Š” ์ฐธ์ด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.๋งŒ์•ฝ condition1์ด ์ฐธ์ด๋ฉด condition2๋Š” ํ‰๊ฐ€๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
  4. if (condition1 || condition2) { // code }

 

์ด๋Ÿฌํ•œ ์‡ผํŠธ์„œํ‚ท ๊ธฐ๋ฒ•์€ ํ”„๋กœ๊ทธ๋žจ์˜ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฒซ ๋ฒˆ์งธ ์กฐ๊ฑด๋งŒ์œผ๋กœ ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์šฐ ๋ถˆํ•„์š”ํ•œ ์ถ”๊ฐ€ ํ‰๊ฐ€๋ฅผ ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด์ž–์Šด~

 

๊ทธ๋ž˜์„œ allMatch, anyMatch, noneMatch ๋ฉ”์„œ๋“œ๋“ค๋„ ๋‚ด๋ถ€์ ์œผ๋กœ ์‡ผํŠธ์„œํ‚ท(short-circuit) ๊ธฐ๋ฒ•์„ ํ™œ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•œ๋‹ค.

 

  1. allMatch: ๋ชจ๋“  ์š”์†Œ๊ฐ€ ์ฃผ์–ด์ง„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์–ด๋–ค ์š”์†Œ๋ผ๋„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ์•Š์œผ๋ฉด ๋’ค์˜ ์š”์†Œ๋“ค์„ ํ‰๊ฐ€ํ•˜์ง€ ์•Š๊ณ  ์ฆ‰์‹œ false๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    1. boolean allMatch = stream.allMatch(element -> element > 0);
  2. anyMatch: ์ ์–ด๋„ ํ•˜๋‚˜์˜ ์š”์†Œ๊ฐ€ ์ฃผ์–ด์ง„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์–ด๋–ค ์š”์†Œ๋ผ๋„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด ๋’ค์˜ ์š”์†Œ๋“ค์„ ํ‰๊ฐ€ํ•˜์ง€ ์•Š๊ณ  ์ฆ‰์‹œ true๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    1. boolean anyMatch = stream.anyMatch(element -> element > 0);
  3. noneMatch: ๋ชจ๋“  ์š”์†Œ๊ฐ€ ์ฃผ์–ด์ง„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜์ง€ ์•Š๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์–ด๋–ค ์š”์†Œ๋ผ๋„ ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋ฉด ๋’ค์˜ ์š”์†Œ๋“ค์„ ํ‰๊ฐ€ํ•˜์ง€ ์•Š๊ณ  ์ฆ‰์‹œ false๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
    1. boolean noneMatch = stream.noneMatch(element -> element < 0);

allMatch๋Š” ๋…ผ๋ฆฌ AND์™€ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•˜๋ฉฐ, anyMatch๋Š” ๋…ผ๋ฆฌ OR์™€ ์œ ์‚ฌํ•˜๊ฒŒ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค. noneMatch๋Š” ์กฐ๊ฑด์„ ๋ถ€์ •ํ•˜์—ฌ allMatch์™€ ๋น„์Šทํ•œ ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.

 

๋˜ํ•œ, ์ด ๋ฉ”์„œ๋“œ๋“ค์„ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ์ฃผ์–ด์ง„ Predicate ์กฐ๊ฑด์— ๋”ฐ๋ผ ๋ชจ๋“  ์š”์†Œ๋ฅผ ํ™•์ธํ•˜์ง€ ์•Š๊ณ ๋„ ์ฆ‰์‹œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ์‡ผํŠธ์„œํ‚ท ๊ธฐ๋ฒ•์ด ์ ์šฉ๋˜์–ด ํšจ์œจ์ ์œผ๋กœ ๋™์ž‘ํ•˜๊ฒŒ ๋˜๋Š”๊ฑฐ์ž–์Šด~

 

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

findAny ๋ฉ”์„œ๋“œ๋ฅผ ๋‹ค๋ฅธ ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ(filter ๊ฐ™์€)๊ณผ ์—ฐ๊ฒฐํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

    @Test
    @DisplayName("findAny๋กœ ์•„๋ฌด ์š”์†Œ๋‚˜ ๋ฐ˜ํ™˜ํ•˜๊ธฐ")
    void findAnyTest() {
        Optional<Dish> optionalDish = menuList.stream()
                .filter(Dish::isVegetarian)
                .findAny();
    }

 

Optional (java.util.Optional)

์˜ต์…”๋„์€ ๊ฐ’์˜ ์กด์žฌ๋‚˜ ๋ถ€์žฌ ์—ฌ๋ถ€๋ฅผ ํ‘œํ˜„ํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ ํด๋ž˜์Šค์ด๋‹ค.

์ž๋ฐ” 8 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค๊ณ„์ž๋“ค์€ null์— ๋Œ€ํ•ด์„œ๋„ ๋งŽ์€ ๊ณ ๋ฏผ์„ ํ–ˆ์—ˆ๋‚˜๋ณด๋‹ค.

null์€ ์‰ฝ๊ฒŒ ์—๋Ÿฌ๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, Optional๋ผ๋Š” ๊ฒƒ์ด ๋งŒ๋“ค์–ด์กŒ๋‹ค.

 

findFirst: ์ฒซ ๋ฒˆ์งธ ์š”์†Œ ์ฐพ๊ธฐ

์—ฐ์†๋˜๋Š” ๋ฐ์ดํ„ฐ๋กœ ๋งŒ๋“  ์ŠคํŠธ๋ฆผ์—์„œ ๋…ผ๋ฆฌ์ ์ธ ์•„์ดํ…œ ์ˆœ์„œ๊ฐ€ ์ •ํ•ด์ ธ ์žˆ์„ ๋•Œ, ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋งŒ ํ•„์š”ํ•  ๋•Œ๊ฐ€ ์žˆ์ž–์Šด?

๊ทธ๋Ÿด ๋•Œ๋Š” findFirst๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.