# JAVA Stream

Java 8๋ฒ„์ „ ์ด์ƒ๋ถ€ํ„ฐ๋Š” Stream API๋ฅผ ์ง€์›ํ•œ๋‹ค


์ž๋ฐ”์—์„œ๋„ 8๋ฒ„์ „ ์ด์ƒ๋ถ€ํ„ฐ ๋žŒ๋‹ค๋ฅผ ์‚ฌ์šฉํ•œ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๊ฐ€๋Šฅํ•ด์กŒ๋‹ค.

๊ธฐ์กด์— ์กด์žฌํ•˜๋˜ Collection๊ณผ Stream์€ ๋ฌด์Šจ ์ฐจ์ด๊ฐ€ ์žˆ์„๊นŒ? ๋ฐ”๋กœ **'๋ฐ์ดํ„ฐ ๊ณ„์‚ฐ ์‹œ์ '**์ด๋‹ค.

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

Collection์€ ํ•ธ๋“œํฐ์— ์Œ์•… ํŒŒ์ผ์„ ๋ฏธ๋ฆฌ ์ €์žฅํ•˜์—ฌ ์žฌ์ƒํ•˜๋Š” ํ”Œ๋ ˆ์ด์–ด๋ผ๋ฉด, Stream์€ ํ•„์š”ํ•  ๋•Œ ๊ฒ€์ƒ‰ํ•ด์„œ ๋“ฃ๋Š” ๋ฉœ๋ก ๊ณผ ๊ฐ™์€ ์Œ์•… ์–ดํ”Œ์ด๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค.


# ์™ธ๋ถ€ ๋ฐ˜๋ณต & ๋‚ด๋ถ€ ๋ฐ˜๋ณต

Collection์€ ์™ธ๋ถ€ ๋ฐ˜๋ณต, Stream์€ ๋‚ด๋ถ€ ๋ฐ˜๋ณต์ด๋ผ๊ณ  ํ–ˆ๋‹ค. ๋‘ ์ฐจ์ด๋ฅผ ์•Œ์•„๋ณด์ž.

**์„ฑ๋Šฅ ๋ฉด์—์„œ๋Š” '๋‚ด๋ถ€ ๋ฐ˜๋ณต'**์ด ๋น„๊ต์  ์ข‹๋‹ค. ๋‚ด๋ถ€ ๋ฐ˜๋ณต์€ ์ž‘์—…์„ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•˜๋ฉด์„œ ์ตœ์ ํ™”๋œ ์ˆœ์„œ๋กœ ์ฒ˜๋ฆฌํ•ด์ค€๋‹ค. ํ•˜์ง€๋งŒ ์™ธ๋ถ€ ๋ฐ˜๋ณต์€ ๋ช…์‹œ์ ์œผ๋กœ ์ปฌ๋ ‰์…˜ ํ•ญ๋ชฉ์„ ํ•˜๋‚˜์”ฉ ๊ฐ€์ ธ์™€์„œ ์ฒ˜๋ฆฌํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ ํ™”์— ๋ถˆ๋ฆฌํ•˜๋‹ค.

์ฆ‰, Collection์—์„œ ๋ณ‘๋ ฌ์„ฑ์„ ์ด์šฉํ•˜๋ ค๋ฉด ์ง์ ‘ synchronized๋ฅผ ํ†ตํ•ด ๊ด€๋ฆฌํ•ด์•ผ๋งŒ ํ•œ๋‹ค.



# Stream ์—ฐ์‚ฐ

์ŠคํŠธ๋ฆผ์€ ์—ฐ์‚ฐ ๊ณผ์ •์ด '์ค‘๊ฐ„'๊ณผ '์ตœ์ข…'์œผ๋กœ ๋‚˜๋ˆ„์–ด์ง„๋‹ค.

filter, map, limit ๋“ฑ ํŒŒ์ดํ”„๋ผ์ด๋‹์ด ๊ฐ€๋Šฅํ•œ ์—ฐ์‚ฐ์„ ์ค‘๊ฐ„ ์—ฐ์‚ฐ, count, collect ๋“ฑ ์ŠคํŠธ๋ฆผ์„ ๋‹ซ๋Š” ์—ฐ์‚ฐ์„ ์ตœ์ข… ์—ฐ์‚ฐ์ด๋ผ๊ณ  ํ•œ๋‹ค.

๋‘˜๋กœ ๋‚˜๋ˆ„๋Š” ์ด์œ ๋Š”, ์ค‘๊ฐ„ ์—ฐ์‚ฐ๋“ค์€ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š”๋ฐ, ๋ชจ๋‘ ํ•œ๊บผ๋ฒˆ์— ๋ณ‘ํ•ฉํ•˜์—ฌ ์—ฐ์‚ฐ์„ ์ฒ˜๋ฆฌํ•œ ๋‹ค์Œ ์ตœ์ข… ์—ฐ์‚ฐ์—์„œ ํ•œ๊บผ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜๊ฒŒ ๋œ๋‹ค.

ex) Item ์ค‘์— ๊ฐ€๊ฒฉ์ด 1000 ์ด์ƒ์ธ ์ด๋ฆ„์„ 5๊ฐœ ์„ ํƒํ•œ๋‹ค.

List<String> items = item.stream()
    			.filter(d->d.getPrices()>=1000)
                          .map(d->d.getName())
                          .limit(5)
                          .collect(tpList());

filter์™€ map์€ ๋‹ค๋ฅธ ์—ฐ์‚ฐ์ด์ง€๋งŒ, ํ•œ ๊ณผ์ •์œผ๋กœ ๋ณ‘ํ•ฉ๋œ๋‹ค.

๋งŒ์•ฝ Collection ์ด์—ˆ๋‹ค๋ฉด, ์šฐ์„  ๊ฐ€๊ฒฉ์ด 1000 ์ด์ƒ์ธ ์•„์ดํ…œ์„ ์ฐพ์€ ๋‹ค์Œ, ์ด๋ฆ„๋งŒ ๋”ฐ๋กœ ์ €์žฅํ•œ ๋’ค 5๊ฐœ๋ฅผ ์„ ํƒํ•ด์•ผ ํ•œ๋‹ค. ์—ฐ์‚ฐ ์ตœ์ ํ™”๋Š” ๋ฌผ๋ก , ๊ฐ€๋…์„ฑ ๋ฉด์—์„œ๋„ Stream์ด ๋” ์ข‹๋‹ค.


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

  • filter(Predicate) : Predicate๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ true์ธ ์š”์†Œ๋ฅผ ํฌํ•จํ•œ ์ŠคํŠธ๋ฆผ ๋ฐ˜ํ™˜
  • distinct() : ์ค‘๋ณต ํ•„ํ„ฐ๋ง
  • limit(n) : ์ฃผ์–ด์ง„ ์‚ฌ์ด์ฆˆ ์ดํ•˜ ํฌ๊ธฐ๋ฅผ ๊ฐ–๋Š” ์ŠคํŠธ๋ฆผ ๋ฐ˜ํ™˜
  • skip(n) : ์ฒ˜์Œ ์š”์†Œ n๊ฐœ ์ œ์™ธํ•œ ์ŠคํŠธ๋ฆผ ๋ฐ˜ํ™˜
  • map(Function) : ๋งคํ•‘ ํ•จ์ˆ˜์˜ result๋กœ ๊ตฌ์„ฑ๋œ ์ŠคํŠธ๋ฆผ ๋ฐ˜ํ™˜
  • flatMap() : ์ŠคํŠธ๋ฆผ์˜ ์ฝ˜ํ…์ธ ๋กœ ๋งคํ•‘ํ•จ. map๊ณผ ๋‹ฌ๋ฆฌ ํ‰๋ฉดํ™”๋œ ์ŠคํŠธ๋ฆผ ๋ฐ˜ํ™˜

์ค‘๊ฐ„ ์—ฐ์‚ฐ์€ ๋ชจ๋‘ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

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

  • (boolean) allMatch(Predicate) : ๋ชจ๋“  ์ŠคํŠธ๋ฆผ ์š”์†Œ๊ฐ€ Predicate์™€ ์ผ์น˜ํ•˜๋Š”์ง€ ๊ฒ€์‚ฌ
  • (boolean) anyMatch(Predicate) : ํ•˜๋‚˜๋ผ๋„ ์ผ์น˜ํ•˜๋Š” ์š”์†Œ๊ฐ€ ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌ
  • (boolean) noneMatch(Predicate) : ๋งค์น˜๋˜๋Š” ์š”์†Œ๊ฐ€ ์—†๋Š”์ง€ ๊ฒ€์‚ฌ
  • (Optional) findAny() : ํ˜„์žฌ ์ŠคํŠธ๋ฆผ์—์„œ ์ž„์˜์˜ ์š”์†Œ ๋ฐ˜ํ™˜
  • (Optional) findFirst() : ์ŠคํŠธ๋ฆผ์˜ ์ฒซ๋ฒˆ์งธ ์š”์†Œ
  • reduce() : ๋ชจ๋“  ์ŠคํŠธ๋ฆผ ์š”์†Œ๋ฅผ ์ฒ˜๋ฆฌํ•ด ๊ฐ’์„ ๋„์ถœ. ๋‘ ๊ฐœ์˜ ์ธ์ž๋ฅผ ๊ฐ€์ง
  • collect() : ์ŠคํŠธ๋ฆผ์„ reduceํ•˜์—ฌ list, map, ์ •์ˆ˜ ํ˜•์‹ ์ปฌ๋ ‰์…˜์„ ๋งŒ๋“ฌ
  • (void) forEach() : ์ŠคํŠธ๋ฆผ ๊ฐ ์š”์†Œ๋ฅผ ์†Œ๋น„ํ•˜๋ฉฐ ๋žŒ๋‹ค ์ ์šฉ
  • (Long) count : ์ŠคํŠธ๋ฆผ ์š”์†Œ ๊ฐœ์ˆ˜ ๋ฐ˜ํ™˜

# Optional ํด๋ž˜์Šค

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

  • null๋กœ ์ธํ•œ ๋ฒ„๊ทธ๋ฅผ ๋ง‰์„ ์ˆ˜ ์žˆ๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.
  • isPresent() : Optional์ด ๊ฐ’์„ ํฌํ•จํ•  ๋•Œ True ๋ฐ˜ํ™˜

# Stream ํ™œ์šฉ ์˜ˆ์ œ

  1. map()

    List<String> names = Arrays.asList("Sehoon", "Songwoo", "Chan", "Youngsuk", "Dajung");
    
    names.stream()
        .map(name -> name.toUpperCase())
        .forEach(name -> System.out.println(name));
    
  2. filter()

    List<String> startsWithN = names.stream()
        .filter(name -> name.startsWith("S"))
        .collect(Collectors.toList());
    
  3. reduce()

    Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
    Optional<Integer> sum = numbers.reduce((x, y) -> x + y);
    sum.ifPresent(s -> System.out.println("sum: " + s));
    

    sum : 55

  4. collect()

    System.out.println(names.stream()
                       .map(String::toUpperCase)
                       .collect(Collectors.joining(", ")));
    


# [์ฐธ๊ณ ์ž๋ฃŒ]

์ตœ์ข… ์ˆ˜์ • : 12/17/2022, 7:23:59 AM