Skip to content

Latest commit

ย 

History

History
519 lines (380 loc) ยท 23.6 KB

File metadata and controls

519 lines (380 loc) ยท 23.6 KB

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

1. ์ŠคํŠธ๋ฆผ ๋„์ž… ์ด์ „๊ณผ ์ดํ›„์˜ ์ฐจ์ด

1) ์ŠคํŠธ๋ฆผ ๋„์ž… ์ด์ „

์ŠคํŠธ๋ฆผ์ด ๋„์ž…๋˜๊ธฐ ์ด์ „์— ์›์†Œ ์‹œํ€€์Šค, ์ฆ‰ ์ผ๋ จ์˜ ์›์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฉ”์„œ๋“œ์˜ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ Collection, Set, List๊ณผ ๊ฐ™์€ ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค๋‚˜ Iterable ๋˜๋Š” ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ–ˆ๋‹ค.

์ผ๋ฐ˜์ ์ธ ๋ฐ˜ํ™˜ ํƒ€์ž…

  • Collection, Set, List:
    • ๊ฐ€์žฅ ๋งŽ์ด ์‚ฌ์šฉ๋˜๋Š” ๊ธฐ๋ณธ ์ธํ„ฐํŽ˜์ด์Šค.
    • ๋ฐ˜๋ณต(iteration)๊ณผ ๋‹ค์–‘ํ•œ ์œ ํ‹ธ๋ฆฌํ‹ฐ ๋ฉ”์„œ๋“œ(size, contains, add, remove ๋“ฑ)๋ฅผ ์ œ๊ณต.
  • Iterable:
    • ๋‹จ์ˆœ ๋ฐ˜๋ณต์„ ์œ„ํ•œ ์ธํ„ฐํŽ˜์ด์Šค.
    • ์ปฌ๋ ‰์…˜๋ณด๋‹ค ๊ฐ„๋‹จํ•œ ์ธํ„ฐํŽ˜์ด์Šค๋กœ, for-each ๋ฃจํ”„์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅ.
  • ๋ฐฐ์—ด(Array):
    • ๊ธฐ๋ณธ ํƒ€์ž…์„ ๋‹ค๋ฃจ๊ฑฐ๋‚˜ ์„ฑ๋Šฅ์ด ์ค‘์š”ํ•œ ๊ฒฝ์šฐ ์‚ฌ์šฉ.
    • ํฌ๊ธฐ๊ฐ€ ๊ณ ์ •๋˜๊ณ , ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค์˜ ์œ ์—ฐ์„ฑ์„ ์ œ๊ณตํ•˜์ง€ ์•Š์Œ.

์„ ํƒ ๊ธฐ์ค€

  1. ๋ฐ˜๋ณต๊ณผ ์ปฌ๋ ‰์…˜ ๋ฉ”์„œ๋“œ ์ œ๊ณต ์—ฌ๋ถ€:
    • ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค๊ฐ€ ์ ํ•ฉ: ๋Œ€๋ถ€๋ถ„์˜ ๊ฒฝ์šฐ, ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉ.
    • ๋‹จ์ˆœ ๋ฐ˜๋ณต๋งŒ ํ•„์š”ํ•œ ๊ฒฝ์šฐ: Iterable ์‚ฌ์šฉ.
  2. ์„ฑ๋Šฅ ๋ฏผ๊ฐ๋„:
    • ๋ฐฐ์—ด์„ ์‚ฌ์šฉํ•˜์—ฌ ์˜ค๋ฒ„ํ—ค๋“œ๋ฅผ ์ค„์ž„.

2) ์ŠคํŠธ๋ฆผ ๋„์ž… ์ดํ›„ : Stream์„ Iterable๋กœ ๋ณ€ํ™˜ ๋ฌธ์ œ์ 

Java 8์—์„œ๋Š” ์ŠคํŠธ๋ฆผ(Stream)์ด ๋“ฑ์žฅํ•˜๋ฉฐ, ์›์†Œ ์‹œํ€€์Šค๋ฅผ ๋ฐ˜ํ™˜ํ•  ๋•Œ ์„ ํƒ์ง€๊ฐ€ ๋ณต์žกํ•ด์กŒ๋‹ค.

์ŠคํŠธ๋ฆผ์€ ๋ฐ˜๋ณต(iteration)์„ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋”ฐ๋ผ์„œ ์›์†Œ ์‹œํ€€์Šค๋ฅผ ๋ฐ˜ํ™˜ํ• ๋•Œ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด for-each ๋กœ ๋ฐ˜๋ณต์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†๋‹ค.

for (ProcessHandle ph : ProcessHandle.allProcesses()::iterator) {
// ํ”„๋กœ์„ธ์Šค๋ฅผ ์ฒ˜๋ฆฌํ•œ๋‹ค.
}
}

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


ํ•˜์ง€๋งŒ ProcessHandle.allProcesses()๋Š” ์ŠคํŠธ๋ฆผ(Stream<ProcessHandle>)์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ, ์ด๋ฅผ for-each์—์„œ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•:

  1. ::iterator๋ฅผ ์‚ฌ์šฉ: ์ŠคํŠธ๋ฆผ์„ Iterable๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ for-each ์‚ฌ์šฉ.
  2. collect()๋กœ ์ปฌ๋ ‰์…˜์œผ๋กœ ๋ณ€ํ™˜: Stream์„ ๋ช…์‹œ์ ์œผ๋กœ List ๋˜๋Š” Set์œผ๋กœ ๋ณ€ํ™˜ํ•˜์—ฌ ์ฒ˜๋ฆฌ.

๊ธฐ์กด ๋ฐฉ๋ฒ•: ::iterator๋กœ Iterable ๋ณ€ํ™˜

@Test
public void processHandleTestUsingIterator() {
    // Stream์„ Iterable๋กœ ๋ณ€ํ™˜
    Iterable<ProcessHandle> processHandles = ProcessHandle.allProcesses()::iterator;

    // for-each ์‚ฌ์šฉ
    for (ProcessHandle processHandle : processHandles) {
        System.out.println("Process Info: " + processHandle.info());
    }
}
  1. ํƒ€์ž… ์ถ”๋ก ์ด ๋ถˆํŽธ:
    • IDE๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ํƒ€์ž…์„ ์ •ํ™•ํžˆ ์ถ”๋ก ํ•˜์ง€ ๋ชปํ•˜๋ฉฐ, ์ˆ˜๋™ ์บ์ŠคํŒ…์ด ํ•„์š”ํ•  ์ˆ˜ ์žˆ์Œ.
    • Runnable, Executable ๋“ฑ ๋‹ค๋ฅธ ํƒ€์ž…์„ ์ถ”์ฒœํ•˜๋Š” ๊ฒฝ์šฐ๋„ ๋ฐœ์ƒ.
  2. ๊ฐ€๋…์„ฑ ์ €ํ•˜:
    • ::iterator ๋ฐฉ์‹์€ ์ง๊ด€์ ์ด์ง€ ์•Š์œผ๋ฉฐ, ์ฝ”๋“œ๋ฅผ ์ฝ๋Š” ์‚ฌ๋žŒ์—๊ฒŒ ํ˜ผ๋ž€์„ ์ค„ ์ˆ˜ ์žˆ์Œ.
public interface Stream<T> extends BaseStream<T, Stream<T>> {
} 

๊ทธ๋ ‡๋‹ค๋ฉด ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜๋ณตํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ?

2. ์ŠคํŠธ๋ฆผ ๋ฐ˜๋ณต์„ ์œ„ํ•œ ํ•ด๊ฒฐ๋ฒ•

1) ์–ด๋Œ‘ํ„ฐ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•œ Stream๊ณผ Iterable ๊ฐ„ ๋ณ€ํ™˜

Java์—์„œ ์ŠคํŠธ๋ฆผ๊ณผ Iterable ํƒ€์ž…์„ ํ•„์š”์— ๋”ฐ๋ผ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ๋„๋ก ์–ด๋Œ‘ํ„ฐ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•˜์—ฌ ์œ ์—ฐํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์ด๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ฑฐ๋‚˜ ๋ฐ˜๋ณตํ•˜๋ ค๋Š” ์ƒํ™ฉ์—์„œ ์ฝ”๋“œ์˜ ํ™œ์šฉ์„ฑ์„ ๋†’์—ฌ์ค€๋‹ค.

์–ด๋Œ‘ํ„ฐ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„

// Stream -> Iterable ๋ณ€ํ™˜ ๋ฉ”์„œ๋“œ
public static <E> Iterable<E> iterableOf(Stream<E> stream) {
    // ์ŠคํŠธ๋ฆผ์˜ iterator() ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ด Iterable ๋ฐ˜ํ™˜
    return stream::iterator;
}

// Iterable -> Stream ๋ณ€ํ™˜ ๋ฉ”์„œ๋“œ
public static <E> Stream<E> streamOf(Iterable<E> iterable) {
    // Iterable์„ Stream์œผ๋กœ ๋ณ€ํ™˜ (Spliterator ์‚ฌ์šฉ)
    return StreamSupport.stream(iterable.spliterator(), false);
}
  • iterableOf()์™€ streamOf()๋ผ๋Š” ๋‘๊ฐ€์ง€ ์–ด๋Œ‘ํ„ฐ ๋ฉ”์„œ๋“œ๋กœ ์„œ๋กœ์˜ ํƒ€์ž…์„ ์‰ฝ๊ฒŒ ์˜ค๊ฐˆ ์ˆ˜ ์žˆ๊ฒŒ ๋งŒ๋“ค์–ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜๋„ ์žˆ๋‹ค.
  • Collection ์ธํ„ฐํŽ˜์ด์Šค๋Š” stream() ๊ณผ Iterable ๊ตฌํ˜„ ๋ชจ๋‘ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์™•์ด๋ฉด Collection ์ด๋‚˜ ๊ทธ ํ•˜์œ„ ํƒ€์ž…์„ ๋ฐ˜ํ™˜ ํ˜น์€ ํŒŒ๋ผ๋ฏธํ„ฐ ํƒ€์ž…์— ์‚ฌ์šฉํ•˜๋Š” ๊ฒŒ ์ตœ์„ ์ด๋‹ค.
  • ๋‹จ์ง€ ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค๋Š” ์ด์œ ๋กœ ๋ฉ์น˜ ํฐ ์‹œํ€€์Šค1๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ ค์„œ๋Š” ์•ˆ๋œ๋‹ค.

์‹œํ€€์Šค๊ฐ€ ํฌ์ง€๋งŒ, ํ‘œํ˜„ ๋ฐฉ์‹์ด ๊ฐ„๋‹จํ•ด์งˆ ์ˆ˜ ์žˆ๋‹ค๋ฉด, ์ „์šฉ ์ปฌ๋ ‰์…˜์„ ๊ตฌํ˜„ํ•ด๋ณด์ž.

์–ด๋Œ‘ํ„ฐ ๋ฉ”์„œ๋“œ ํ™œ์šฉ ์˜ˆ์ œ : ์–ด๋Œ‘ํ„ฐ ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•œ Stream -> Iterable -> Stream ๋ณ€ํ™˜ ์˜ˆ์ œ

@Test
void streamIterableTest() {
    // ProcessHandle ์ŠคํŠธ๋ฆผ ์ƒ์„ฑ
    Stream<ProcessHandle> handleStream = ProcessHandle.allProcesses();

    // ์ŠคํŠธ๋ฆผ์„ ์ด์šฉํ•œ ํ”„๋กœ์„ธ์Šค ์ •๋ณด ์ถœ๋ ฅ
    handleStream.forEach(p -> System.out.println(p.info()));

    // Stream -> Iterable ๋ณ€ํ™˜ ํ›„ for-each ๋ฌธ ์‚ฌ์šฉ
    Iterable<ProcessHandle> handles = iterableOf(handleStream);
    for (ProcessHandle handle : handles) {
        System.out.println(handle.info());
    }

    // Iterable -> Stream ๋ณ€ํ™˜ ํ›„ ๋‹ค์‹œ ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ
    Stream<ProcessHandle> stream = streamOf(handles);
    stream.forEach(p -> System.out.println(p.info()));
}
  • ์ŠคํŠธ๋ฆผ ํ™œ์šฉ์ด ๊ฐ„๋‹จํ•œ ๊ฒฝ์šฐ: ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๊ณ  ์ง์ ‘ forEach()๋ฅผ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ž.
  • Iterable ํƒ€์ž…์„ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ: ์–ด๋Œ‘ํ„ฐ ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ŠคํŠธ๋ฆผ์„ Iterable๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ ์ปฌ๋ ‰์…˜์œผ๋กœ ์ˆ˜์ง‘(collect())ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๊ณ ๋ คํ•˜์ž.

2) ์ปฌ๋ ‰์…˜์ด ๋” ์ ํ•ฉํ•œ ๊ฒฝ์šฐ: ๋ฉฑ์ง‘ํ•ฉ ๊ตฌํ•˜๊ธฐ

๋ฉฑ์ง‘ํ•ฉ(Power Set)์€ ๋ชจ๋“  ๋ถ€๋ถ„ ์ง‘ํ•ฉ์„ ์›์†Œ๋กœ ๊ฐ€์ง€๋Š” ์ง‘ํ•ฉ์„ ๋งํ•œ๋‹ค. ์ด ๊ฒฝ์šฐ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ฆฌ๊ธฐ๋ณด๋‹ค๋Š” ํ•„์š”ํ•œ ์‹œ์ ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด ๋” ํšจ์œจ์ ์ด๋‹ค.

๋ฉฑ์ง‘ํ•ฉ์„ ์œ„ํ•œ ์ „์šฉ ์ปฌ๋ ‰์…˜ ๊ตฌํ˜„

์ž…๋ ฅ ์ง‘ํ•ฉ์˜ ์›์†Œ ์ˆ˜๊ฐ€ 30์„ ๋„˜์œผ๋ฉด PowerSet.of๊ฐ€ ์˜ˆ์™ธ๋ฅผ ๋˜์ง„๋‹ค. ์ด๋Š” Stream์ด๋‚˜ Iterable์ด ์•„๋‹Œ Collection์„ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์“ธ ๋•Œ์˜ ๋‹จ์ ์„ ์ž˜ ๋ณด์—ฌ์ค€๋‹ค. ๋‹ค์‹œ ๋งํ•ด, Collection์˜ size ๋ฉ”์„œ๋“œ๊ฐ€ int ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋ฏ€๋กœ PowerSet.of๊ฐ€ ๋ฐ˜ํ™˜๋˜๋Š” ์‹œํ€€์Šค์˜ ์ตœ๋Œ€ ๊ธธ์ด๋Š” Integer.MAX_VALUE ํ˜น์€ 2^n-1๋กœ ์ œํ•œ๋œ๋‹ค. Collection ๋ช…์„ธ์— ๋”ฐ๋ฅด๋ฉด ์ปฌ๋ ‰์…˜์ด ๋” ํฌ๊ฑฐ๋‚˜ ์‹ฌ์ง€์–ด ๋ฌดํ•œ๋Œ€์ผ ๋•Œ size๊ฐ€ 2^n-1์„ ๋ฐ˜ํ™˜ํ•ด๋„ ๋˜์ง€๋งŒ ์™„์ „ํžˆ ๋งŒ์กฑ ์Šค๋Ÿฌ์šด ํ•ด๋ฒ•์€ ์•„๋‹ˆ๋‹ค.

static class PowerSet {
    public static final <E> Collection<Set<E>> of(Set<E> s) {
        List<E> src = new ArrayList<>(s);
        int numberOfMaximumElements = 30; // ์›์†Œ ๊ฐœ์ˆ˜ ์ œํ•œ (์ตœ๋Œ€ 30)

        if (src.size() > numberOfMaximumElements) {
            throw new IllegalArgumentException("์ง‘ํ•ฉ์— ์›์†Œ๊ฐ€ ๋„ˆ๋ฌด ๋งŽ์Šต๋‹ˆ๋‹ค. (์ตœ๋Œ€ " + numberOfMaximumElements + " ๊ฐœ)");
        }

        // AbstractList๋ฅผ ์ด์šฉํ•ด ํ•„์š”ํ•œ ๋ถ€๋ถ„์ง‘ํ•ฉ์„ ๋™์ ์œผ๋กœ ์ƒ์„ฑ
        return new AbstractList<>() {
            @Override
            public Set<E> get(int index) {
                Set<E> result = new HashSet<>();
                for (int i = 0; index != 0; i++, index >>= 1) {
                    if ((index & 1) == 1) {
                        result.add(src.get(i));
                    }
                }
                return result;
            }

            @Override
            public int size() {
                // ๋ฉฑ์ง‘ํ•ฉ์˜ ํฌ๊ธฐ = 2^์›์†Œ์˜ ์ˆ˜
                return 1 << src.size();
            }

            @Override
            public boolean contains(Object o) {
                return o instanceof Set && src.containsAll((Set<?>) o);
            }
        };
    
  • ๋ฉฑ์ง‘ํ•ฉ์„ ๊ตฌํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ์—” ๊ตณ์ด ํ•ญ์ƒ ๋ชจ๋“  ์ปฌ๋ ‰์…˜ ์š”์†Œ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์ƒ์— ์˜ฌ๋ฆฌ๊ณ  ์žˆ์„ ํ•„์š”๋Š” ์—†๋‹ค.
  • get() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ํ•„์š”ํ•œ ์‹œ์ ์— ํ•„์š”ํ•œ ์—˜๋ฆฌ๋จผํŠธ๋ฅผ ์–ป์œผ๋ฉด ๋œ๋‹ค.
  • ๋ชจ๋“  ์š”์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๊ธฐ์—” 2^length๋งŒํผ์˜ ๊ณต๊ฐ„์„ ํ™•๋ณดํ•ด์•ผ ํ•˜๋Š” ๋ถ€๋‹ด์ด ์žˆ๋‹ค.
  • ๋ชจ๋“  ์š”์†Œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉด ๋งค๋ฒˆ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ƒ๊ธธ ๋•Œ๋งˆ๋‹ค ๋ฉฑ์ง‘ํ•ฉ์„ ์ƒˆ๋กœ ๊ตฌํ•ด์•ผ ํ•œ๋‹ค.
  • AbstractCollection ์€ contains() ์™€ size() ๋งŒ ๊ตฌํ˜„ํ•ด์ฃผ๋ฉด ๊ตฌํ˜„ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋œ๋‹ค.
  • ์ด ๊ฒฝ์šฐ๊ฐ€ Collection ์„ ๋ฐ˜ํ™˜ํ•˜๊ธฐ ์ ๋‹นํ•œ ํ˜•ํƒœ๋‹ค.
    • Stream ์€ size ๋ฅผ ๊ตฌํ•  ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ด ๊ฒฝ์šฐ์— ์ ํ•ฉํ•˜์ง€ ์•Š๋‹ค.

{% hint style="info" %} ์ถ”์ฒœ์‚ฌํ•ญ {% endhint %}

  • ํฐ ์‹œํ€€์Šค๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ: ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋ฉ”๋ชจ๋ฆฌ์— ์˜ฌ๋ฆฌ๊ธฐ๋ณด๋‹ค ํ•„์š”ํ•œ ์‹œ์ ์— ๋™์ ์œผ๋กœ ์ƒ์„ฑํ•˜๋„๋ก ์„ค๊ณ„ํ•˜์ž.
  • ์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ : ๋ฉฑ์ง‘ํ•ฉ๊ณผ ๊ฐ™์ด ๋ฐ์ดํ„ฐ ์žฌ์‚ฌ์šฉ์ด ์ค‘์š”ํ•˜๊ฑฐ๋‚˜, ๋ฐ˜๋ณต(iteration)์ด ๋งŽ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ์— ์ ํ•ฉํ•˜๋‹ค.

{% hint style="danger" %} Stream์— size() ๋˜๋Š” length๊ฐ€ ์—†๋Š” ์ด์œ  {% endhint %}

๊ฒŒ์œผ๋ฅธ ํ‰๊ฐ€๋กœ ์ธํ•ด ์ „์ฒด ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ๋ฅผ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ

  1. ๊ฒŒ์œผ๋ฅธ ํ‰๊ฐ€๋กœ ์ธํ•ด ์ •ํ™•ํ•œ ํฌ๊ธฐ ์˜ˆ์ธก ๋ถˆ๊ฐ€:
    • ์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ๋ฅผ ํ•„์š”ํ•  ๋•Œ๋งŒ ๊ฒŒ์œผ๋ฅด๊ฒŒ ํ‰๊ฐ€ํ•œ๋‹ค.
    • ํ‰๊ฐ€๊ฐ€ ์ด๋ฃจ์–ด์ง€๊ธฐ ์ „๊นŒ์ง€, ๋ฐ์ดํ„ฐ๊ฐ€ ๋ช‡ ๊ฐœ์˜ ์›์†Œ๋ฅผ ํฌํ•จํ• ์ง€ ์•Œ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์—, ์ •ํ™•ํ•œ ํฌ๊ธฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” size()์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์—†๋‹ค.
  2. ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜์˜ ๋ถˆํ™•์‹ค์„ฑ:
    • ์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜์„ ์—ฌ๋Ÿฌ ๋‹จ๊ณ„์— ๊ฑธ์ณ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๋ณ€ํ™˜ ๊ณผ์ •์—์„œ ํ•„ํ„ฐ๋ง๋˜๊ฑฐ๋‚˜ ์ถ”๊ฐ€๋˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ตœ์ข… ํฌ๊ธฐ๋ฅผ ์˜ˆ์ธกํ•˜๊ธฐ ์–ด๋ ต๋‹ค.
  3. ๋Œ€์‹  count() ๋ฉ”์„œ๋“œ ์ œ๊ณต:
    • ์ŠคํŠธ๋ฆผ์€ size() ๋Œ€์‹  count() ๋ฉ”์„œ๋“œ๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
    • count() ๋ฉ”์„œ๋“œ๋Š” ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ ๊ฐœ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๋ฐ˜ํ™˜ํ•˜์ง€๋งŒ, ์ŠคํŠธ๋ฆผ์„ ์†Œ๋ชจํ•œ๋‹ค. ์ฆ‰, ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ ์†Œ๋น„ํ•˜์—ฌ ๊ฐœ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ดํ›„์—๋Š” ํ•ด๋‹น ์ŠคํŠธ๋ฆผ์„ ๋‹ค์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

count() ์‚ฌ์šฉ ์˜ˆ์ œ

Stream<String> names = Stream.of("Alice", "Bob", "Charlie");
long count = names.count();  // ์ŠคํŠธ๋ฆผ์˜ ์›์†Œ ๊ฐœ์ˆ˜ ๋ฐ˜ํ™˜ (3)
  • count()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ŠคํŠธ๋ฆผ์˜ ๊ฐœ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•  ์ˆ˜ ์žˆ์ง€๋งŒ, ์ด ๊ณผ์ •์—์„œ ์ŠคํŠธ๋ฆผ์ด ์†Œ๋ชจ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ดํ›„์— ๋™์ผํ•œ ์ŠคํŠธ๋ฆผ์„ ๋‹ค์‹œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

3) ์ŠคํŠธ๋ฆผ์ด ๋” ์ ํ•ฉํ•œ ๊ฒฝ์šฐ: ๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ

๋ฆฌ์ŠคํŠธ์˜ ๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์ฒ˜๋ฆฌํ•˜๋Š” ์ž‘์—…์€ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ„๊ฒฐํ•˜๊ณ  ๊ฐ€๋…์„ฑ์ด ์ข‹๋‹ค.

๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ ์ŠคํŠธ๋ฆผ ์ƒ์„ฑ

static class SubLists {
    // ์ฃผ์–ด์ง„ ๋ฆฌ์ŠคํŠธ์˜ ๋ชจ๋“  ์ ‘๋‘์‚ฌ์™€ ์ ‘๋ฏธ์‚ฌ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ฐ˜ํ™˜
    public static <E> Stream<List<E>> of(List<E> list) {
        Stream<List<E>> prefixes = prefixes(list);
        Stream<List<E>> suffixes = suffixes(list);

        return Stream.concat(prefixes, suffixes);
    }

    // ๋ฆฌ์ŠคํŠธ์˜ ๋ชจ๋“  ์ ‘๋‘์‚ฌ ๋ฐ˜ํ™˜
    private static <E> Stream<List<E>> prefixes(List<E> list) {
        return IntStream.rangeClosed(1, list.size())
                .mapToObj(end -> list.subList(0, end));
    }

    // ๋ฆฌ์ŠคํŠธ์˜ ๋ชจ๋“  ์ ‘๋ฏธ์‚ฌ ๋ฐ˜ํ™˜
    private static <E> Stream<List<E>> suffixes(List<E> list) {
        return IntStream.range(0, list.size())
                .mapToObj(start -> list.subList(start, list.size()));
    }
}

๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ ์ŠคํŠธ๋ฆผ ํ™œ์šฉ ์˜ˆ์ œ

@Test
void subListStreamTest() {
    List<String> list = Arrays.asList("A", "B", "C", "D");

    // ๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ ๋ฐ ์ฒ˜๋ฆฌ
    SubLists.of(list).forEach(subList -> System.out.println("SubList: " + subList));
}
  • ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜์ด๋‚˜ ํ•„ํ„ฐ๋ง์ด ์ฃผ์š”ํ•œ ๊ฒฝ์šฐ, ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌ
  • ๋ถ€๋ถ„ ๋ฆฌ์ŠคํŠธ์™€ ๊ฐ™์€ ๋ฐ˜๋ณต์ด ์ž์—ฐ์Šค๋Ÿฌ์šด ๊ฒฝ์šฐ ์ŠคํŠธ๋ฆผ์ด ๊ฐ€๋…์„ฑ๊ณผ ์„ฑ๋Šฅ ๋ชจ๋‘์—์„œ ๋” ์œ ๋ฆฌ๋‹ค.

4) ์ถ”๊ฐ€ ์ฝ”๋“œ ์˜ˆ์ œ์™€ ์ฃผ์„

์ŠคํŠธ๋ฆผ์„ ์ด์šฉํ•œ ๊ฐ„๋‹จํ•œ ํ•„ํ„ฐ๋ง ๋ฐ ๋ณ€ํ™˜

@Test
void streamFilteringTest() {
    List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

    // ์ด๋ฆ„์ด 'A'๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ด๋ฆ„๋งŒ ํ•„ํ„ฐ๋งํ•˜๊ณ  ๋ชจ๋‘ ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜
    names.stream()
         .filter(name -> name.startsWith("A"))    // 'A'๋กœ ์‹œ์ž‘ํ•˜๋Š” ์ด๋ฆ„ ํ•„ํ„ฐ๋ง
         .map(String::toUpperCase)                // ๋Œ€๋ฌธ์ž๋กœ ๋ณ€ํ™˜
         .forEach(System.out::println);           // ์ถœ๋ ฅ

    // ์ถœ๋ ฅ ๊ฒฐ๊ณผ: ALICE
}

์ปฌ๋ ‰์…˜์„ ์‚ฌ์šฉํ•œ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

@Test
void collectionReuseTest() {
    List<String> items = Arrays.asList("apple", "banana", "cherry");

    // ์ฒซ ๋ฒˆ์งธ ๋ฐ˜๋ณต: ๊ฐ ์•„์ดํ…œ์„ ์ถœ๋ ฅ
    for (String item : items) {
        System.out.println("Item: " + item);
    }

    // ๋‘ ๋ฒˆ์งธ ๋ฐ˜๋ณต: ๊ฐ ์•„์ดํ…œ์˜ ๊ธธ์ด ์ถœ๋ ฅ
    for (String item : items) {
        System.out.println("Item length: " + item.length());
    }
}
  • ์ปฌ๋ ‰์…˜ ์‚ฌ์šฉ ์ด์œ : ๋ฐ์ดํ„ฐ๋ฅผ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜๋ณตํ•˜๊ฑฐ๋‚˜ ์žฌ์‚ฌ์šฉํ•ด์•ผ ํ•  ๋•Œ ์ปฌ๋ ‰์…˜์ด ๋” ์ ํ•ฉํ•˜๋‹ค.
  • ์ŠคํŠธ๋ฆผ์€ ์ผํšŒ์„ฑ ์‚ฌ์šฉ์ด ๊ธฐ๋ณธ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ˜๋ณต ์‚ฌ์šฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ์ปฌ๋ ‰์…˜์ด ๋” ํšจ์œจ์ ์ด๋‹ค.

๐Ÿ“š ํ•ต์‹ฌ ์ •๋ฆฌ

{% hint style="success" %} Stream ์€ ๋ฐ˜ํ™˜ ํƒ€์ž…์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ๋ณด๋‹ค๋Š” ๋‹จ์ˆœํžˆ ์ปฌ๋ ‰์…˜ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ๋ฐ˜ํ™˜์€ ๋‹ค์‹œ ์ปฌ๋ ‰์…˜์œผ๋กœ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š” ๊ฒƒ์ด ํ™œ์šฉ์„ฑ์ด ์ข‹๋‹ค. someStream.collect(Collectors.toList()) ์™€ ๊ฐ™์€ ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜๋ฉด ์‰ฝ๋‹ค. {% endhint %}

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

์ปฌ๋ ‰์…˜์€ ๋ฐ˜๋ณต๊ณผ ์žฌ์‚ฌ์šฉ์— ์ ํ•ฉํ•˜๊ณ , ์ŠคํŠธ๋ฆผ์€ ๋ณ€ํ™˜๊ณผ ์ฒ˜๋ฆฌ์— ๋” ๊ฐ•๋ ฅ

  • ์ŠคํŠธ๋ฆผ์€ ๋‚˜๋ฆ„๋Œ€๋กœ์˜ ์žฅ๋‹จ์ ์ด ์žˆ์–ด์„œ, ๊ฒฝ์šฐ์— ๋งž๊ฒŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.
  • ๊ฐ€์žฅ ํฐ ์žฅ์ ์ด์ž ๋‹จ์ ์ด ์ง€์—ฐ ํ‰๊ฐ€๊ฐ€ ๋œ๋‹ค๋Š” ๊ฒƒ์ด๋‹ค.
  • ๊ธฐ๋ณธ์ ์œผ๋กœ๋Š” ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒŒ ์œ ์—ฐํ•˜๋‹ค. ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ์ปฌ๋ ‰์…˜์„ ๋ฐ˜ํ™˜ํ•˜์—ฌ stream()๊ณผ for-each๋ฅผ ๋ชจ๋‘ ์ง€์›ํ•˜๋„๋ก ํ•˜๊ณ , ๋ฐ์ดํ„ฐ๊ฐ€ ํฌ๊ฑฐ๋‚˜ ์ผํšŒ์„ฑ์ด๋ผ๋ฉด ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค.

{% hint style="success" %} ์ปฌ๋ ‰์…˜ ์‚ฌ์šฉ ์ถ”์ฒœ ์‹œ์ : {% endhint %}

  • ๋ฐ์ดํ„ฐ๊ฐ€ ์—ฌ๋Ÿฌ ๋ฒˆ ๋ฐ˜๋ณต๋˜๊ฑฐ๋‚˜ ์žฌ์‚ฌ์šฉ์ด ํ•„์š”ํ•  ๋•Œ.
  • ๋ฐ์ดํ„ฐ์˜ ์ „์ฒด ํฌ๊ธฐ๋ฅผ ํŒŒ์•…ํ•ด์•ผ ํ•  ๋•Œ.

{% hint style="success" %} ์ŠคํŠธ๋ฆผ ์‚ฌ์šฉ ์ถ”์ฒœ ์‹œ์ : {% endhint %}

  • ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜ ๋ฐ ํ•„ํ„ฐ๋ง์ด ์ฃผ์š” ์ž‘์—…์ผ ๋•Œ.
  • ์ง€์—ฐ ์‹คํ–‰์„ ํ†ตํ•ด ํšจ์œจ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•  ๋•Œ.

๐Ÿ“š ์ฐธ๊ณ  : ์ŠคํŠธ๋ฆผ์—์„œ ํ‰๊ฐ€๋ž€?

1) ์ŠคํŠธ๋ฆผ์—์„œ ํ‰๊ฐ€(Evaluation)๋ž€?

ํ‰๊ฐ€(Evaluation)๋Š” ์ŠคํŠธ๋ฆผ์ด ์—ฐ์‚ฐ์„ ๋๋‚ด๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ๊ณผ์ •์„ ์˜๋ฏธํ•œ๋‹ค.
์ŠคํŠธ๋ฆผ์€ ์ง€์—ฐ ์‹คํ–‰(Lazy Evaluation)์„ ํ†ตํ•ด ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์ฒ˜๋ฆฌํ•˜๋ฉฐ, ์ตœ์ข… ์—ฐ์‚ฐ(Terminal Operation)์ด ํ˜ธ์ถœ๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค. ํ‰๊ฐ€ ๋‹จ๊ณ„์—์„œ ์ŠคํŠธ๋ฆผ์€ ๋” ์ด์ƒ ์ŠคํŠธ๋ฆผ ํƒ€์ž…(Stream)์ด ์•„๋‹ˆ๋ฉฐ, ๊ฒฐ๊ณผ๋ฅผ ํŠน์ • ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋ฐ˜ํ™˜ํ•œ๋‹ค.

ํ‰๊ฐ€์˜ ์˜๋ฏธ

ํ‰๊ฐ€๋Š” ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ์ด ์™„๋ฃŒ๋˜์–ด ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋˜๋Š” ์ƒํƒœ๋ฅผ ๋งํ•œ๋‹ค.
๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ตœ์ข… ์—ฐ์‚ฐ(Terminal Operation)์„ ํ†ตํ•ด ํ‰๊ฐ€๊ฐ€ ์ด๋ฃจ์–ด์ง„๋‹ค:

  1. ๋ฐ์ดํ„ฐ๋ฅผ ์ปฌ๋ ‰์…˜, ๋ฐฐ์—ด ๋“ฑ์œผ๋กœ ๋ณ€ํ™˜:
    • ์˜ˆ: toArray(), collect()
  2. ์—ฐ์‚ฐ ๊ฒฐ๊ณผ๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ์ถ•์†Œ:
    • ์˜ˆ: reduce()
  3. ๋ฐ์ดํ„ฐ๋ฅผ ์†Œ๋น„ํ•˜๊ฑฐ๋‚˜ ์ถœ๋ ฅ:
    • ์˜ˆ: forEach()
  4. ๋‹จ์ผ ์กฐ๊ฑด์„ ํ‰๊ฐ€:
    • ์˜ˆ: findFirst(), anyMatch(), allMatch()

2) ํ‰๊ฐ€์˜ ํŠน์ง•

์ŠคํŠธ๋ฆผ์€ ํ‰๊ฐ€ ์ „๊นŒ์ง€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค (์ง€์—ฐ ์‹คํ–‰)

  • ์ค‘๊ฐ„ ์—ฐ์‚ฐ(Intermediate Operation)์€ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ํ•˜๋Š” ์ž‘์—…์„ ์ •์˜ํ•˜์ง€๋งŒ, ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค.
  • ์ŠคํŠธ๋ฆผ์€ ์ตœ์ข… ์—ฐ์‚ฐ(Terminal Operation)์ด ํ˜ธ์ถœ๋  ๋•Œ๋งŒ ์‹คํ–‰๋œ๋‹ค.

์˜ˆ์ œ: ์ง€์—ฐ ์‹คํ–‰

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");

// ์ค‘๊ฐ„ ์—ฐ์‚ฐ: ์‹คํ–‰๋˜์ง€ ์•Š์Œ
Stream<String> stream = names.stream()
                             .filter(name -> {
                                 System.out.println("Filtering: " + name);
                                 return name.startsWith("A");
                             });

// ์ตœ์ข… ์—ฐ์‚ฐ: ์—ฌ๊ธฐ์„œ ํ‰๊ฐ€๊ฐ€ ๋ฐœ์ƒ
List<String> result = stream.collect(Collectors.toList());
// ์ถœ๋ ฅ:
// Filtering: Alice
// Filtering: Bob
// Filtering: Charlie
  • filter๋Š” ์ค‘๊ฐ„ ์—ฐ์‚ฐ์œผ๋กœ ์ •์˜๋งŒ ๋˜์—ˆ์œผ๋ฉฐ, ์‹ค์ œ๋กœ ๋ฐ์ดํ„ฐ๋Š” ์ฒ˜๋ฆฌ๋˜์ง€ ์•Š๋Š”๋‹ค.
  • collect๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด์„œ ์ŠคํŠธ๋ฆผ์ด ํ‰๊ฐ€๋˜๊ณ  ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

๋‹จ๋ฝ ์กฐ๊ฑด (Short-Circuiting Condition)

  • ์ผ๋ถ€ ์ตœ์ข… ์—ฐ์‚ฐ์€ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜์ง€ ์•Š๊ณ ๋„ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋‹จ๋ฝ ์กฐ๊ฑด์€ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋  ์ˆ˜ ์žˆ๋Š” ์กฐ๊ฑด์„ ๋งํ•œ๋‹ค.

๋‹จ๋ฝ ์กฐ๊ฑด์ด ์ ์šฉ๋˜๋Š” ์—ฐ์‚ฐ

์—ฐ์‚ฐ์„ค๋ช…์˜ˆ์‹œ
findFirst()์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ์ฐพ์œผ๋ฉด ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ๊ฐ€ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค.stream.findFirst()
anyMatch()์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๋ฅผ ํ•˜๋‚˜๋ผ๋„ ์ฐพ์œผ๋ฉด ์ฒ˜๋ฆฌ ์ข…๋ฃŒ.stream.anyMatch(x -> x > 10)
allMatch()์กฐ๊ฑด์ด ๋ชจ๋“  ์š”์†Œ์— ๋งŒ์กฑํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ ์ฆ‰์‹œ ์ฒ˜๋ฆฌ ์ข…๋ฃŒ.stream.allMatch(x -> x > 0)
noneMatch()์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š” ์š”์†Œ๊ฐ€ ํ•˜๋‚˜๋„ ์—†์„ ๊ฒฝ์šฐ ์ฒ˜๋ฆฌ ์ข…๋ฃŒ.stream.noneMatch(x -> x < 0)
limit(n)์ตœ๋Œ€ n๊ฐœ์˜ ์š”์†Œ๋งŒ ์ฒ˜๋ฆฌํ•˜๊ณ  ํ‰๊ฐ€๋ฅผ ์ข…๋ฃŒ.stream.limit(5).collect(Collectors.toList())

๋‹จ๋ฝ ์กฐ๊ฑด ์˜ˆ์ œ

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

// ๋‹จ๋ฝ ์กฐ๊ฑด: ์ฒซ ๋ฒˆ์งธ ์š”์†Œ ๋ฐœ๊ฒฌ ์‹œ ์ฒ˜๋ฆฌ ์ข…๋ฃŒ
Optional<Integer> first = numbers.stream()
                                 .filter(n -> n > 3)
                                 .findFirst();
System.out.println(first.get()); // ์ถœ๋ ฅ: 4
  • findFirst๋Š” ์กฐ๊ฑด์— ๋งž๋Š” ์ฒซ ๋ฒˆ์งธ ์š”์†Œ๋ฅผ ์ฐพ์œผ๋ฉด ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ๋ฅผ ์ข…๋ฃŒํ•œ๋‹ค.

3. ํ‰๊ฐ€๊ฐ€ ๋ฐœ์ƒํ•˜๋Š” ์ตœ์ข… ์—ฐ์‚ฐ

์ตœ์ข… ์—ฐ์‚ฐ์€ ์ŠคํŠธ๋ฆผ์„ ํ‰๊ฐ€ํ•˜๋ฉฐ, ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ฑฐ๋‚˜ ๋ฐ์ดํ„ฐ ์†Œ๋น„๋ฅผ ์™„๋ฃŒํ•ฉ๋‹ˆ๋‹ค.

3-1. ์ปฌ๋ ‰์…˜์œผ๋กœ ๋ณ€ํ™˜

  • toList(): ์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ๋ฅผ List๋กœ ๋ณ€ํ™˜.
  • toSet(): ์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ๋ฅผ Set์œผ๋กœ ๋ณ€ํ™˜.
  • toMap(): ํ‚ค-๊ฐ’ ๋งคํ•‘์„ ๊ธฐ๋ฐ˜์œผ๋กœ Map์œผ๋กœ ๋ณ€ํ™˜.

์˜ˆ์ œ

List<String> result = Stream.of("a", "b", "c").collect(Collectors.toList());
System.out.println(result); // ์ถœ๋ ฅ: [a, b, c]

3-2. ์ถ•์†Œ (Reduction)

  • ์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ๋ฅผ ํ•˜๋‚˜์˜ ๊ฐ’์œผ๋กœ ์ถ•์†Œ.
  • ์˜ˆ: reduce(), count(), max(), min().

์˜ˆ์ œ

int sum = Stream.of(1, 2, 3, 4, 5)
                .reduce(0, Integer::sum); // ์ดˆ๊ธฐ๊ฐ’ 0, ํ•ฉ์‚ฐ ์—ฐ์‚ฐ
System.out.println(sum); // ์ถœ๋ ฅ: 15

3-3. ์กฐ๊ฑด ๊ฒ€์‚ฌ

  • ๋ฐ์ดํ„ฐ๊ฐ€ ํŠน์ • ์กฐ๊ฑด์„ ๋งŒ์กฑํ•˜๋Š”์ง€ ๊ฒ€์‚ฌ.
  • ์˜ˆ: anyMatch(), allMatch(), noneMatch().

์˜ˆ์ œ

boolean hasNegative = Stream.of(1, 2, -3, 4, 5)
                            .anyMatch(n -> n < 0);
System.out.println(hasNegative); // ์ถœ๋ ฅ: true

3-4. ๋ฐ์ดํ„ฐ ์†Œ๋น„

  • ๋ฐ์ดํ„ฐ๋ฅผ ์ˆœํšŒํ•˜๋ฉฐ ์†Œ๋น„.
  • ์˜ˆ: forEach(), forEachOrdered().

์˜ˆ์ œ

Stream.of("a", "b", "c").forEach(System.out::println);
// ์ถœ๋ ฅ:
// a
// b
// c

4. ํ‰๊ฐ€์™€ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ

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

๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ํ‰๊ฐ€ ์˜ˆ์ œ

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6);

// ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์œผ๋กœ sum ๊ณ„์‚ฐ
int sum = numbers.parallelStream()
                 .reduce(0, Integer::sum);
System.out.println(sum); // ์ถœ๋ ฅ: 21
  • ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ ์š”์†Œ๋ฅผ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉฐ, ์ตœ์ข… ๊ฒฐ๊ณผ๋ฅผ ๊ฒฐํ•ฉํ•ฉ๋‹ˆ๋‹ค.
  • ํ‰๊ฐ€ ๊ณผ์ •์—์„œ๋„ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋ฏ€๋กœ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์— ์œ ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

5. ์š”์•ฝ

  • ํ‰๊ฐ€(Evaluation): ์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ๊ฐ€ ์ตœ์ข… ์—ฐ์‚ฐ์„ ํ†ตํ•ด ํŠน์ • ์ž๋ฐ” ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜๋˜๋Š” ๊ณผ์ •.
  • ํ‰๊ฐ€ ๋ฐœ์ƒ ์กฐ๊ฑด: ์ตœ์ข… ์—ฐ์‚ฐ์ด ํ˜ธ์ถœ๋  ๋•Œ๋งŒ ํ‰๊ฐ€๊ฐ€ ์ด๋ฃจ์–ด์ง.
  • ๋‹จ๋ฝ ์กฐ๊ฑด: ํŠน์ • ์กฐ๊ฑด์— ๋”ฐ๋ผ ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ๊ฐ€ ์ค‘๋‹จ๋  ์ˆ˜ ์žˆ์Œ (findFirst, anyMatch ๋“ฑ).
  • ์ง€์—ฐ ์‹คํ–‰: ์ŠคํŠธ๋ฆผ์€ ํ‰๊ฐ€ ์ „๊นŒ์ง€ ์‹คํ–‰๋˜์ง€ ์•Š์œผ๋ฉฐ, ์ •์˜๋งŒ ์ด๋ฃจ์–ด์ง.
  • ์ตœ์ข… ์—ฐ์‚ฐ ์ข…๋ฅ˜:
    • ๋ฐ์ดํ„ฐ ์†Œ๋น„: forEach
    • ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜: collect, toList, toMap
    • ๋ฐ์ดํ„ฐ ์ถ•์†Œ: reduce, count, max, min
    • ์กฐ๊ฑด ๊ฒ€์‚ฌ: anyMatch, allMatch, findFirst

์ŠคํŠธ๋ฆผ ํ‰๊ฐ€๋ฅผ ์ž˜ ํ™œ์šฉํ•˜๋ฉด ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•˜๊ณ , ๊ฐ€๋…์„ฑ๊ณผ ์„ฑ๋Šฅ์„ ๋ชจ๋‘ ๋†’์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ถœ์ฒ˜ ๋ฐ ์ฐธ๊ณ 

Footnotes

  1. ๋ฉ์น˜ ํฐ ์‹œํ€€์Šค๋ž€, ๋ฐ์ดํ„ฐ์˜ ํฌ๊ธฐ(์›์†Œ์˜ ๊ฐœ์ˆ˜๋‚˜ ๋ฐ์ดํ„ฐ ์–‘)๊ฐ€ ๋งค์šฐ ํฐ ๊ฒฝ์šฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋ฆฌ์ŠคํŠธ, ๋ฐฐ์—ด, ์ŠคํŠธ๋ฆผ ๋“ฑ์—์„œ ์›์†Œ์˜ ๊ฐœ์ˆ˜๊ฐ€ ๋งŽ์•„์ ธ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ๋Ÿ‰์ด๋‚˜ ๊ณ„์‚ฐ๋Ÿ‰์ด ๋งค์šฐ ์ปค์ง„ ์‹œํ€€์Šค๋ฅผ ๋งํ•ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฉ์น˜ ํฐ ์‹œํ€€์Šค๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ๋Š” ๋ฉ”๋ชจ๋ฆฌ ํšจ์œจ์„ฑ, ์„ฑ๋Šฅ ๋ฌธ์ œ, ์ฒ˜๋ฆฌ ์†๋„ ๋“ฑ์„ ๊ณ ๋ คํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    ๋ฉ์น˜ ํฐ ์‹œํ€€์Šค์˜ ์˜ˆ์‹œ

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