** ๐Ÿ“Œ1๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ(Stream)์ด๋ž€? ์‰ฝ๊ฒŒ ์ดํ•ดํ•˜๊ธฐ**

๐ŸŽฏ ๊ฐ•๋ฌผ๊ณผ ๊ฐ™์€ ๋ฐ์ดํ„ฐ ํ๋ฆ„!

์ŠคํŠธ๋ฆผ์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ•๋ฌผ์ฒ˜๋Ÿผ ํ๋ฅด๊ฒŒ ํ•˜๋ฉด์„œ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด์—์š”.

๐Ÿ’ง ๋น„์œ :

๐Ÿ’ก ์ŠคํŠธ๋ฆผ์˜ ํŠน์ง•

โœ” ๋ฐ์ดํ„ฐ๋ฅผ ์ง์ ‘ ์ €์žฅํ•˜์ง€ ์•Š๊ณ , โ€œํ๋ฆ„โ€๋งŒ ๋‹ค๋ฃฌ๋‹ค.

โœ” ์ค‘๊ฐ„ ์—ฐ์‚ฐ(ํ•„ํ„ฐ๋ง, ๋ณ€ํ™˜)์€ ์‹ค์ œ ์‹คํ–‰๋˜์ง€ ์•Š๋‹ค๊ฐ€, ์ตœ์ข… ์—ฐ์‚ฐ(์ถœ๋ ฅ, ํ•ฉ๊ณ„ ๋“ฑ)์„ ๋งŒ๋‚˜์•ผ ์‹คํ–‰๋จ.

โœ” ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ(์—ฌ๋Ÿฌ ๊ฐœ์˜ CPU ์‚ฌ์šฉ ๊ฐ€๋Šฅ)๋กœ ๋น ๋ฅด๊ฒŒ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์Œ.

๐Ÿ“ ์˜ˆ์ œ: 70์  ์ด์ƒ์ธ ํ•™์ƒ๋งŒ ๊ฑธ๋Ÿฌ๋‚ด๊ธฐ

List<Integer> scores = Arrays.asList(50, 60, 70, 80, 90);
List<Integer> highScores = scores.stream()
                                 .filter(score -> score >= 70)
                                 .collect(Collectors.toList());
System.out.println(highScores); // [70, 80, 90]

2๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์˜ ๊ตฌ์กฐ (์–ด๋””์„œ ๋‚˜์™€์„œ ์–ด๋””๋กœ ๊ฐ€๋‚˜?)

๐Ÿ“Œ ์ŠคํŠธ๋ฆผ์˜ 3๋‹จ๊ณ„ ๊ตฌ์กฐ

๋‹จ๊ณ„ ์„ค๋ช… ์˜ˆ์ œ
1. ์†Œ์Šค(Source) ๋ฐ์ดํ„ฐ๊ฐ€ ์ถœ๋ฐœํ•˜๋Š” ๊ณณ ๋ฆฌ์ŠคํŠธ, ๋ฐฐ์—ด, ํŒŒ์ผ, ํ‚ค๋ณด๋“œ ์ž…๋ ฅ
2. ์ค‘๊ฐ„ ์—ฐ์‚ฐ(Intermediate) ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ˜•, ํ•„ํ„ฐ๋ง filter(), map(), sorted()
3. ์ตœ์ข… ์—ฐ์‚ฐ(Terminal) ๋ฐ์ดํ„ฐ๋ฅผ ์ตœ์ข…์ ์œผ๋กœ ์‚ฌ์šฉ forEach(), count(), collect()

๐Ÿ“ ์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•˜๋ฉด?

List<String> fruits = Arrays.asList("์‚ฌ๊ณผ", "๋ฐ”๋‚˜๋‚˜", "๋”ธ๊ธฐ");

// 1. ์†Œ์Šค (๋ฐ์ดํ„ฐ ์ถœ๋ฐœ)
Stream<String> stream = fruits.stream();

// 2. ์ค‘๊ฐ„ ์—ฐ์‚ฐ (ํ•„ํ„ฐ๋ง: 3๊ธ€์ž ์ด์ƒ๋งŒ ๋‚จ๊ธฐ๊ธฐ)
Stream<String> filteredStream = stream.filter(fruit -> fruit.length() >= 3);

// 3. ์ตœ์ข… ์—ฐ์‚ฐ (๊ฐœ์ˆ˜ ์„ธ๊ธฐ)
long count = filteredStream.count();
System.out.println("3๊ธ€์ž ์ด์ƒ ๊ณผ์ผ ๊ฐœ์ˆ˜: " + count);

โœ” ์†Œ์Šค โ†’ ์ค‘๊ฐ„ ์ฒ˜๋ฆฌ(ํ•„ํ„ฐ) โ†’ ์ตœ์ข… ์‚ฌ์šฉ(์ถœ๋ ฅ, ์ €์žฅ ๋“ฑ) ์ˆœ์„œ๋กœ ์ง„ํ–‰!


3๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์˜ ๋™์ž‘ ๋ฐฉ์‹ (๋‚ด๋ถ€ ๋ฐ˜๋ณต & ์ง€์—ฐ ์—ฐ์‚ฐ)

๐Ÿ”„ ๊ธฐ์กด ๋ฐฉ์‹(์™ธ๋ถ€ ๋ฐ˜๋ณต) vs ์ŠคํŠธ๋ฆผ ๋ฐฉ์‹(๋‚ด๋ถ€ ๋ฐ˜๋ณต)

๋ฐฉ์‹ ์„ค๋ช… ์˜ˆ์ œ
์™ธ๋ถ€ ๋ฐ˜๋ณต(๊ธฐ์กด for๋ฌธ) ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ for ์‚ฌ์šฉ
๋‚ด๋ถ€ ๋ฐ˜๋ณต(์ŠคํŠธ๋ฆผ) ์ŠคํŠธ๋ฆผ์ด ์•Œ์•„์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ forEach() ์‚ฌ์šฉ

๐Ÿ“ ์˜ˆ์ œ: ๋‚ด๋ถ€ ๋ฐ˜๋ณต์˜ ๋™์ž‘ ๋ฐฉ์‹

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

names.stream()
     .map(name -> {
         System.out.println("๋ณ€ํ™˜ ์ค‘: " + name);
         return name.toUpperCase();
     })
     .forEach(System.out::println);

โœ” ์ตœ์ข… ์—ฐ์‚ฐ(forEach())์ด ์‹คํ–‰๋˜๊ธฐ ์ „๊นŒ์ง€ map()์ด ์‹คํ–‰๋˜์ง€ ์•Š์Œ! (์ง€์—ฐ ์—ฐ์‚ฐ)


4๋‹จ๊ณ„: ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ(Parallel Stream)๊ณผ ์„ฑ๋Šฅ ์ตœ์ ํ™”

๐Ÿš€ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์ด๋ž€?

๐Ÿ“ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์˜ˆ์ œ (๋ณ‘๋ ฌ ์‹คํ–‰ ํ™•์ธํ•˜๊ธฐ)

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

names.parallelStream()
     .map(name -> {
         System.out.println("์ฒ˜๋ฆฌ ์ค‘: " + name + " - " + Thread.currentThread().getName());
         return name.toUpperCase();
     })
     .forEach(System.out::println);

๐Ÿ’ก ์ถœ๋ ฅ ๊ฒฐ๊ณผ:

์ฒ˜๋ฆฌ ์ค‘: Alice - ForkJoinPool.commonPool-worker-1
์ฒ˜๋ฆฌ ์ค‘: Bob - ForkJoinPool.commonPool-worker-2
์ฒ˜๋ฆฌ ์ค‘: Charlie - ForkJoinPool.commonPool-worker-3
์ฒ˜๋ฆฌ ์ค‘: David - ForkJoinPool.commonPool-worker-1

โœ” ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์—์„œ ๋™์‹œ์— ์‹คํ–‰๋จ!

๐Ÿšจ ์ฃผ์˜:


5๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ๊ณผ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ (๋žŒ๋‹ค & ๋ถˆ๋ณ€์„ฑ ํ™œ์šฉ)

๐ŸŽฏ ์ŠคํŠธ๋ฆผ๊ณผ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ฐฐ๋–ก๊ถํ•ฉ!

๐Ÿ“ ์˜ˆ์ œ: ์ˆœ์ˆ˜ ํ•จ์ˆ˜ & ๋ถˆ๋ณ€์„ฑ ์œ ์ง€ํ•˜๊ธฐ

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

// ์›๋ณธ ๋ฐ์ดํ„ฐ ๋ณ€๊ฒฝ ์—†์ด ์ƒˆ๋กœ์šด ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ
List<Integer> doubledNumbers = numbers.stream()
                                      .map(n -> n * 2)
                                      .collect(Collectors.toList());

System.out.println(doubledNumbers); // [2, 4, 6, 8, 10]
System.out.println(numbers); // [1, 2, 3, 4, 5] (์›๋ณธ ๋ฐ์ดํ„ฐ ์œ ์ง€)

6๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์˜ ๊ณ ๊ธ‰ ์—ฐ์‚ฐ (์ง‘๊ณ„, ๊ทธ๋ฃนํ™”, ๋ถ„ํ• )

๐Ÿ“Œ ์ง‘๊ณ„ ์—ฐ์‚ฐ

์—ฐ์‚ฐ ์„ค๋ช… ์˜ˆ์ œ
count() ๊ฐœ์ˆ˜ ์„ธ๊ธฐ .count()
sum() ํ•ฉ๊ณ„ ๊ตฌํ•˜๊ธฐ .mapToInt().sum()
max() ์ตœ๋Œ€๊ฐ’ ์ฐพ๊ธฐ .mapToInt().max()
min() ์ตœ์†Œ๊ฐ’ ์ฐพ๊ธฐ .mapToInt().min()

๐Ÿ“ ์˜ˆ์ œ: ์ ์ˆ˜์˜ ํ‰๊ท  & ์ตœ๋Œ€๊ฐ’ ๊ตฌํ•˜๊ธฐ

List<Integer> scores = Arrays.asList(90, 80, 95, 85, 70);

double average = scores.stream().mapToInt(Integer::intValue).average().orElse(0);
int max = scores.stream().mapToInt(Integer::intValue).max().orElse(0);

System.out.println("ํ‰๊ท : " + average);
System.out.println("์ตœ๋Œ€๊ฐ’: " + max);

7๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ ์„ฑ๋Šฅ ์ตœ์ ํ™” & ์‹ค์ „ ํŒ

๐Ÿš€ ์ตœ์ ํ™” ํ•ต์‹ฌ ํฌ์ธํŠธ!

โœ” ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ ์ค„์ด๊ธฐ

โœ” ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ํ™œ์šฉ (๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ์— ํ•œ์ •!)

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream().mapToInt(n -> n * 2).sum();

โœ” toArray() ์‚ฌ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ ๊ฐœ์„ 

String[] result = names.stream().map(String::toUpperCase).toArray(String[]::new);

๐ŸŽฏ ๊ฒฐ๋ก : ์ŠคํŠธ๋ฆผ ๋งˆ์Šคํ„ฐํ•˜๊ธฐ!

โœ… 1๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ ๊ฐœ๋… ์ดํ•ด (๊ฐ•๋ฌผ์ฒ˜๋Ÿผ ํ๋ฅด๋Š” ๋ฐ์ดํ„ฐ)

โœ… 2๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ ๊ตฌ์กฐ (์†Œ์Šค โ†’ ์ค‘๊ฐ„ ์—ฐ์‚ฐ โ†’ ์ตœ์ข… ์—ฐ์‚ฐ)

โœ… 3๋‹จ๊ณ„: ๋‚ด๋ถ€ ๋ฐ˜๋ณต & ์ง€์—ฐ ์—ฐ์‚ฐ

โœ… 4๋‹จ๊ณ„: ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ํ™œ์šฉ๋ฒ•

โœ… 5๋‹จ๊ณ„: ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ๊ณผ ์ŠคํŠธ๋ฆผ

โœ… 6๋‹จ๊ณ„: ๊ณ ๊ธ‰ ์—ฐ์‚ฐ (์ง‘๊ณ„, ๊ทธ๋ฃนํ™”, ๋ถ„ํ• )

โœ… 7๋‹จ๊ณ„: ์„ฑ๋Šฅ ์ตœ์ ํ™” & ์‹ค์ „ ํŒ


8๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์˜ ๊ณ ๊ธ‰ ํ™œ์šฉ (Collector & ์ปค์Šคํ…€ ์—ฐ์‚ฐ)

์ง€๊ธˆ๊นŒ์ง€ collect() ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฆฌ์ŠคํŠธ๋กœ ๋ชจ์œผ๊ฑฐ๋‚˜ ์ง‘๊ณ„ํ•˜๋Š” ๋ฒ•์„ ๋ฐฐ์› ์–ด์š”.

์ด์ œ ๊ณ ๊ธ‰ Collector ๊ธฐ๋Šฅ์„ ๋ฐฐ์›Œ๋ณผ๊ฒŒ์š”!


1๏ธโƒฃ Collectors์˜ ๊ฐ•๋ ฅํ•œ ๊ธฐ๋Šฅ๋“ค

๐Ÿ“Œ 1. ๊ทธ๋ฃนํ™” (groupingBy)

Collectors.groupingBy() ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํŠน์ • ๊ธฐ์ค€์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ฃนํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ’ก ์˜ˆ์ œ: ํ•™์ƒ๋“ค์˜ ์ ์ˆ˜๋ฅผ A, B, C ๋“ฑ๊ธ‰์œผ๋กœ ๊ทธ๋ฃนํ™”

List<Student> students = Arrays.asList(
    new Student("Alice", 90),
    new Student("Bob", 80),
    new Student("Charlie", 95),
    new Student("David", 85),
    new Student("Eve", 70)
);

// ์ ์ˆ˜ ๋“ฑ๊ธ‰๋ณ„๋กœ ๊ทธ๋ฃนํ™”
Map<String, List<Student>> groupedByGrade = students.stream()
    .collect(Collectors.groupingBy(s -> {
        if (s.score >= 90) return "A";
        else if (s.score >= 80) return "B";
        else return "C";
    }));

System.out.println(groupedByGrade);

โœ… ๊ฒฐ๊ณผ: {A=[Alice, Charlie], B=[Bob, David], C=[Eve]}


๐Ÿ“Œ 2. ๋ถ„ํ•  (partitioningBy)

Collectors.partitioningBy() ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ๋‘ ๊ฐœ์˜ ๊ทธ๋ฃน(True / False) ์œผ๋กœ ๋‚˜๋ˆŒ ๋•Œ ์‚ฌ์šฉํ•ด์š”.

๐Ÿ’ก ์˜ˆ์ œ: ์ง์ˆ˜ & ํ™€์ˆ˜ ๋ถ„ํ• 

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

Map<Boolean, List<Integer>> partitioned = numbers.stream()
    .collect(Collectors.partitioningBy(n -> n % 2 == 0));

System.out.println("์ง์ˆ˜: " + partitioned.get(true));
System.out.println("ํ™€์ˆ˜: " + partitioned.get(false));

โœ… ๊ฒฐ๊ณผ:

์ง์ˆ˜: [2, 4, 6, 8, 10]
ํ™€์ˆ˜: [1, 3, 5, 7, 9]

๐Ÿ“Œ 3. ๋งคํ•‘ (mapping)

Collectors.mapping() ์„ ์‚ฌ์šฉํ•˜๋ฉด ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ’ก ์˜ˆ์ œ: ๋“ฑ๊ธ‰๋ณ„ ํ•™์ƒ ์ด๋ฆ„๋งŒ ์ถœ๋ ฅ

Map<String, List<String>> groupedNames = students.stream()
    .collect(Collectors.groupingBy(
        s -> s.score >= 90 ? "A" : s.score >= 80 ? "B" : "C",
        Collectors.mapping(s -> s.name, Collectors.toList())
    ));

System.out.println(groupedNames);

โœ… ๊ฒฐ๊ณผ: {A=[Alice, Charlie], B=[Bob, David], C=[Eve]}


2๏ธโƒฃ ์ปค์Šคํ…€ Collector ๋งŒ๋“ค๊ธฐ

๊ธฐ๋ณธ ์ œ๊ณต๋˜๋Š” Collectors.toList() ๊ฐ™์€ ๊ธฐ๋Šฅ์„ ๋„˜์–ด์„œ, ์ง์ ‘ Collector๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์–ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: ๋ชจ๋“  ๋ฌธ์ž์—ด์„ ์‰ผํ‘œ(,)๋กœ ์—ฐ๊ฒฐํ•˜๋Š” Collector

Collector<String, StringBuilder, String> joiningCollector =
    Collector.of(
        StringBuilder::new,
        (sb, s) -> sb.append(s).append(", "),
        StringBuilder::append,
        StringBuilder::toString
    );

String result = Stream.of("Java", "Python", "C++")
                      .collect(joiningCollector);

System.out.println(result);  // Java, Python, C++,

โœ… ์ง์ ‘ Collector.of() ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์ปค์Šคํ…€ ์—ฐ์‚ฐ์„ ๋งŒ๋“ค์—ˆ์–ด์š”!


9๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์˜ ๋””๋ฒ„๊น… & ์ตœ์ ํ™”

์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋‹ค ๋ณด๋ฉด, ์„ฑ๋Šฅ ๋ฌธ์ œ๋‚˜ ์˜ˆ์ƒ๊ณผ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ๋งˆ์ฃผํ•  ์ˆ˜ ์žˆ์–ด์š”.

์ด๋Ÿด ๋•Œ ์ŠคํŠธ๋ฆผ์„ ๋””๋ฒ„๊น…ํ•˜๊ณ  ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์›Œ๋ณผ๊ฒŒ์š”.


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ ๋””๋ฒ„๊น… (peek ํ™œ์šฉ)

์ค‘๊ฐ„ ์—ฐ์‚ฐ์ด ์–ด๋–ป๊ฒŒ ์‹คํ–‰๋˜๋Š”์ง€ ํ™•์ธํ•˜๋ ค๋ฉด peek() ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ผ์š”!

๐Ÿ’ก ์˜ˆ์ œ: ์ŠคํŠธ๋ฆผ์˜ ์‹คํ–‰ ์ˆœ์„œ๋ฅผ ์ถ”์ 

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

names.stream()
     .filter(name -> {
         System.out.println("ํ•„ํ„ฐ๋ง: " + name);
         return name.startsWith("A");
     })
     .peek(name -> System.out.println("peek: " + name))
     .map(String::toUpperCase)
     .forEach(System.out::println);

โœ… ์ถœ๋ ฅ ๊ฒฐ๊ณผ:

ํ•„ํ„ฐ๋ง: Alice
peek: Alice
ALICE
ํ•„ํ„ฐ๋ง: Bob
ํ•„ํ„ฐ๋ง: Charlie

โœ” peek() ๋•๋ถ„์— ํ•„ํ„ฐ ํ›„ ์–ด๋–ค ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚จ์•˜๋Š”์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”!


2๏ธโƒฃ ์„ฑ๋Šฅ ์ตœ์ ํ™” (์—ฐ์‚ฐ ์ˆœ์„œ ๋ณ€๊ฒฝ)

์ŠคํŠธ๋ฆผ์˜ ์—ฐ์‚ฐ ์ˆœ์„œ๋ฅผ ์ž˜ ์กฐ์ •ํ•˜๋ฉด ์„ฑ๋Šฅ์ด ํ™• ์ข‹์•„์งˆ ์ˆ˜ ์žˆ์–ด์š”!

๐Ÿš€ ๋น„ํšจ์œจ์ ์ธ ์ฝ”๋“œ (map์„ ๋จผ์ € ์‹คํ–‰)

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

List<String> result = names.stream()
    .map(name -> name.toUpperCase())  // โŒ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ (๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ ๋ฐœ์ƒ)
    .filter(name -> name.startsWith("A"))
    .collect(Collectors.toList());

โœ… ์ตœ์ ํ™”๋œ ์ฝ”๋“œ (filter๋ฅผ ๋จผ์ € ์‹คํ–‰)

List<String> result = names.stream()
    .filter(name -> name.startsWith("A"))  // โœ… ๋จผ์ € ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ๋‚จ๊น€
    .map(String::toUpperCase)
    .collect(Collectors.toList());

โœ” ๋ถˆํ•„์š”ํ•œ ๋ณ€ํ™˜ ์—ฐ์‚ฐ์„ ์ค„์—ฌ ์„ฑ๋Šฅ์„ ํ–ฅ์ƒ!


3๏ธโƒฃ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์ตœ์ ํ™” (parallelStream ์‚ฌ์šฉ๋ฒ•)

๐Ÿš€ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

โœ… ๋ฐ์ดํ„ฐ ํฌ๊ธฐ๊ฐ€ ํฌ๊ณ  ์—ฐ์‚ฐ์ด ๋ณต์žกํ•  ๋•Œ

โœ… ๋…๋ฆฝ์ ์ธ ์—ฐ์‚ฐ (์ˆœ์„œ, ์ƒํƒœ ๊ณต์œ  X)

โš  ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์ด ๋น„ํšจ์œจ์ ์ธ ๊ฒฝ์šฐ

โŒ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๊ฐ€ ์ ์„ ๋•Œ (์˜ค๋ฒ„ํ—ค๋“œ ๋ฐœ์ƒ)

โŒ ์ •๋ ฌ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ (๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๊ฐ€ ๋” ๋А๋ฆผ)

๐Ÿ’ก ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์ตœ์ ํ™” ์˜ˆ์ œ

List<Integer> numbers = IntStream.range(1, 1000000).boxed().collect(Collectors.toList());

// ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์„ฑ๋Šฅ ๋น„๊ต
long start = System.currentTimeMillis();
numbers.parallelStream().mapToInt(n -> n * 2).sum();
long end = System.currentTimeMillis();
System.out.println("๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ ์‹œ๊ฐ„: " + (end - start) + "ms");

โœ” ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ๋•Œ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋ฉด ์†๋„๊ฐ€ ๋นจ๋ผ์งˆ ์ˆ˜ ์žˆ์Œ!


๐ŸŽฏ ๊ฒฐ๋ก : ์ŠคํŠธ๋ฆผ ์™„๋ฒฝ ๋งˆ์Šคํ„ฐ!

โœ… 8๋‹จ๊ณ„: Collector์˜ ๊ณ ๊ธ‰ ๊ธฐ๋Šฅ (๊ทธ๋ฃนํ™”, ๋ถ„ํ• , ๋งคํ•‘, ์ปค์Šคํ…€ Collector)

โœ… 9๋‹จ๊ณ„: ๋””๋ฒ„๊น… (peek()) & ์„ฑ๋Šฅ ์ตœ์ ํ™” (filter() โ†’ map(), parallelStream())


๐Ÿ”Ÿ 10๋‹จ๊ณ„: ์‹ค์ „ ํ”„๋กœ์ ํŠธ์—์„œ ์ŠคํŠธ๋ฆผ ํ™œ์šฉํ•˜๊ธฐ

์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ŠคํŠธ๋ฆผ์„ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ฒ˜๋ฆฌ, ํŒŒ์ผ ์ž…์ถœ๋ ฅ, API ์‘๋‹ต ์ฒ˜๋ฆฌ ๋“ฑ ๋‹ค์–‘ํ•œ ๊ณณ์—์„œ ํ™œ์šฉํ•ด์š”.

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


1๏ธโƒฃ JSON ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ & ์ŠคํŠธ๋ฆผ ํ™œ์šฉ

๋ฐฑ์—”๋“œ ๊ฐœ๋ฐœ์„ ํ•˜๋‹ค ๋ณด๋ฉด JSON ๋ฐ์ดํ„ฐ๋ฅผ ํŒŒ์‹ฑํ•˜๊ณ  ์ฒ˜๋ฆฌํ•  ์ผ์ด ๋งŽ์•„์š”.

์ž๋ฐ”์—์„œ๋Š” Jackson ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•ด JSON์„ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•œ ํ›„, ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ’ก ์˜ˆ์ œ: JSON ๋ฐ์ดํ„ฐ์—์„œ ํŠน์ • ์กฐ๊ฑด์— ๋งž๋Š” ์‚ฌ์šฉ์ž๋งŒ ์ถ”์ถœํ•˜๊ธฐ

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import java.util.stream.Collectors;

class User {
    public String name;
    public int age;
}

public class JsonStreamExample {
    public static void main(String[] args) throws Exception {
        String json = "[{\"name\":\"Alice\", \"age\":25}, {\"name\":\"Bob\", \"age\":30}, {\"name\":\"Charlie\", \"age\":28}]";

        // JSON์„ ๊ฐ์ฒด ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜
        ObjectMapper objectMapper = new ObjectMapper();
        List<User> users = objectMapper.readValue(json, objectMapper.getTypeFactory().constructCollectionType(List.class, User.class));

        // 30์„ธ ๋ฏธ๋งŒ ์‚ฌ์šฉ์ž๋งŒ ์ถ”์ถœ
        List<String> youngUsers = users.stream()
                .filter(user -> user.age < 30)
                .map(user -> user.name)
                .collect(Collectors.toList());

        System.out.println("30์„ธ ๋ฏธ๋งŒ ์‚ฌ์šฉ์ž: " + youngUsers); // [Alice, Charlie]
    }
}

โœ… ์‹ค์ „์—์„œ API ์‘๋‹ต(JSON) ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•˜๋Š” ๋ฐ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”!


2๏ธโƒฃ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค (JPA + Stream) ํ™œ์šฉํ•˜๊ธฐ

Spring Boot + JPA ํ™˜๊ฒฝ์—์„œ๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณตํ•  ๋•Œ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ’ก ์˜ˆ์ œ: JPA๋กœ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ํ•„ํ„ฐ๋งํ•˜๊ธฐ

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
    List<User> findAll();
}

@Service
public class UserService {
    @Autowired
    private UserRepository userRepository;

    public List<User> getYoungUsers() {
        return userRepository.findAll().stream()
                .filter(user -> user.getAge() < 30)
                .collect(Collectors.toList());
    }
}

โœ… JPA์—์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๊ฐ€๊ณตํ•˜๋ฉด ์ฝ”๋“œ๊ฐ€ ๋” ์ง๊ด€์ ์ด์—์š”!


3๏ธโƒฃ ํŒŒ์ผ ์ž…์ถœ๋ ฅ (๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ)

ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ๊ณ , ํŠน์ • ์กฐ๊ฑด์— ๋งž๊ฒŒ ํ•„ํ„ฐ๋งํ•˜๊ฑฐ๋‚˜ ๊ฐ€๊ณตํ•  ๋•Œ ์ŠคํŠธ๋ฆผ์ด ์œ ์šฉํ•ด์š”.

๐Ÿ’ก ์˜ˆ์ œ: ๋กœ๊ทธ ํŒŒ์ผ์—์„œ ERROR ๋กœ๊ทธ๋งŒ ์ถ”์ถœํ•˜๊ธฐ

import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class LogFilter {
    public static void main(String[] args) throws Exception {
        try (Stream<String> lines = Files.lines(Paths.get("server.log"))) {
            lines.filter(line -> line.contains("ERROR"))
                 .forEach(System.out::println);
        }
    }
}

โœ… ๋Œ€์šฉ๋Ÿ‰ ๋กœ๊ทธ ํŒŒ์ผ๋„ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋ฉด ํšจ์œจ์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”!


4๏ธโƒฃ API ์‘๋‹ต ์ฒ˜๋ฆฌ (WebClient + Stream ํ™œ์šฉ)

Spring WebFlux์˜ WebClient์™€ ์ŠคํŠธ๋ฆผ์„ ๊ฒฐํ•ฉํ•˜๋ฉด ๋น„๋™๊ธฐ API ์‘๋‹ต ์ฒ˜๋ฆฌ๋„ ๊ฐ€๋Šฅํ•ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: ์™ธ๋ถ€ API์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์•„์™€ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๊ฐ€๊ณตํ•˜๊ธฐ

import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

public class ApiClient {
    public static void main(String[] args) {
        WebClient client = WebClient.create("https://jsonplaceholder.typicode.com");

        Flux<String> userNames = client.get()
                .uri("/users")
                .retrieve()
                .bodyToFlux(User.class)
                .map(User::getName);  // ์ŠคํŠธ๋ฆผ(map)์ฒ˜๋Ÿผ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€๊ณต

        userNames.subscribe(System.out::println);  // ๋น„๋™๊ธฐ ์‘๋‹ต ์ฒ˜๋ฆฌ
    }
}

โœ… ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜๋ฉด API ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ํšจ๊ณผ์ ์œผ๋กœ ๊ฐ€๊ณตํ•  ์ˆ˜ ์žˆ์–ด์š”!


๐ŸŽฏ 10๋‹จ๊ณ„ ์š”์•ฝ

โœ… JSON ๋ฐ์ดํ„ฐ์—์„œ ์กฐ๊ฑด์— ๋งž๋Š” ๊ฐ’ ํ•„ํ„ฐ๋ง (ObjectMapper + Stream)

โœ… JPA์—์„œ ๊ฐ€์ ธ์˜จ ๋ฐ์ดํ„ฐ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๊ฐ€๊ณต (Spring Boot + JPA)

โœ… ํŒŒ์ผ ์ž…์ถœ๋ ฅ์—์„œ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ (Files.lines() + Stream)

โœ… API ์‘๋‹ต ๋ฐ์ดํ„ฐ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ฒ˜๋ฆฌ (WebClient + Stream)

์ด์ œ ์‹ค์ œ ํ”„๋กœ์ ํŠธ์—์„œ ์ŠคํŠธ๋ฆผ์„ ์ ๊ทน์ ์œผ๋กœ ํ™œ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๊นŒ์ง€ ๋ฐฐ์› ์–ด์š”! ๐Ÿš€

๐Ÿ”Ÿ+1 11๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์˜ ํ•œ๊ณ„ & ๋Œ€์ฒด ๊ธฐ์ˆ  ๋น„๊ต

์ŠคํŠธ๋ฆผ์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ๋ชจ๋“  ๊ฒฝ์šฐ์— ์ตœ์ ์˜ ์†”๋ฃจ์…˜์€ ์•„๋‹ˆ์—์š”!

์ด ๋‹จ๊ณ„์—์„œ๋Š” ์ŠคํŠธ๋ฆผ์˜ ํ•œ๊ณ„์™€ ๋Œ€์ฒด ๊ธฐ์ˆ ์„ ๋น„๊ตํ•ด๋ณผ๊ฒŒ์š”.


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ์˜ ํ•œ๊ณ„

๐Ÿ”ด ์ŠคํŠธ๋ฆผ์ด ๋ถˆ๋ฆฌํ•œ ๊ฒฝ์šฐ

1๏ธโƒฃ ์ƒํƒœ(State)๋ฅผ ์œ ์ง€ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ

2๏ธโƒฃ ์˜ˆ์™ธ(Exception) ์ฒ˜๋ฆฌ ์–ด๋ ค์›€

3๏ธโƒฃ ๋””๋ฒ„๊น…์ด ์–ด๋ ค์›€


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ vs ๋Œ€์ฒด ๊ธฐ์ˆ  ๋น„๊ต

๊ธฐ๋Šฅ ์ŠคํŠธ๋ฆผ for๋ฌธ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ
๋ฐ์ดํ„ฐ ๊ฐ€๊ณต (ํ•„ํ„ฐ๋ง, ๋ณ€ํ™˜) โœ… ์ง๊ด€์ , ๊ฐ„๊ฒฐํ•จ โŒ ์ฝ”๋“œ ๊ธธ์–ด์ง โŒ ๋ณ‘๋ ฌํ™” ์–ด๋ ค์›€
์ƒํƒœ ๋ณ€๊ฒฝ โŒ ๋ถˆ๊ฐ€๋Šฅ (๋ถˆ๋ณ€์„ฑ ์œ ์ง€) โœ… ๊ฐ€๋Šฅ โœ… ๊ฐ€๋Šฅ
๋””๋ฒ„๊น… ์šฉ์ด์„ฑ โŒ ์–ด๋ ค์›€ โœ… ์‰ฌ์›€ โŒ ๋™์‹œ์„ฑ ๋ฌธ์ œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ
๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ โœ… ํšจ๊ณผ์  โŒ ๋น„ํšจ์œจ์  โœ… ํšจ๊ณผ์  (Parallel Stream)
๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ โœ… parallelStream() ์‚ฌ์šฉ โŒ ์ง์ ‘ ์“ฐ๋ ˆ๋“œ ๊ตฌํ˜„ ํ•„์š” โœ… ๊ฐ€๋Šฅ (ForkJoinPool)

๐Ÿ“Œ ์ŠคํŠธ๋ฆผ์ด ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ: ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต์ด ๋งŽ๊ณ , ์ฝ”๋“œ ๊ฐ€๋…์„ฑ์ด ์ค‘์š”ํ•œ ๊ฒฝ์šฐ

๐Ÿ“Œ for๋ฌธ์ด ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ: ์ƒํƒœ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•˜๊ฑฐ๋‚˜, ๋””๋ฒ„๊น…์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ

๐Ÿ“Œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ(ForkJoinPool)๊ฐ€ ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ: ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ + CPU ํ™œ์šฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ


๐ŸŽฏ 11๋‹จ๊ณ„ ์š”์•ฝ

โœ… ์ŠคํŠธ๋ฆผ์ด ๋ถˆ๋ฆฌํ•œ ๊ฒฝ์šฐ (์ƒํƒœ ๋ณ€๊ฒฝ, ์˜ˆ์™ธ ์ฒ˜๋ฆฌ, ๋””๋ฒ„๊น… ๋ฌธ์ œ)

โœ… ์ŠคํŠธ๋ฆผ vs for๋ฌธ vs ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ๋น„๊ต (๊ฐ๊ฐ์˜ ์žฅ๋‹จ์  ์ดํ•ดํ•˜๊ธฐ)

์ด์ œ ์ŠคํŠธ๋ฆผ์˜ ์žฅ์ ๊ณผ ํ•œ๊ณ„๋ฅผ ์™„๋ฒฝํ•˜๊ฒŒ ์ดํ•ดํ•˜๊ณ , ์ƒํ™ฉ์— ๋งž๊ฒŒ ์ ์ ˆํ•œ ๋ฐฉ๋ฒ•์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์–ด์š”! ๐Ÿš€


###


๐Ÿ”Ÿ+2 12๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ ์„ฑ๋Šฅ ์ตœ์ ํ™” & ์‹ค์ „ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ

์ด ๋‹จ๊ณ„์—์„œ๋Š” ์ŠคํŠธ๋ฆผ์˜ ์„ฑ๋Šฅ์„ ๊ทน๋Œ€ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•๊ณผ ์‹ค์ „ ์„ฑ๋Šฅ ํ…Œ์ŠคํŠธ ๊ธฐ๋ฒ•์„ ๋ฐฐ์šธ ๊ฑฐ์˜ˆ์š”.


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ ์„ฑ๋Šฅ์„ ๋†’์ด๋Š” ๋ฐฉ๋ฒ•

๐Ÿš€ 1. Stream vs ParallelStream ๋น„๊ต

์ŠคํŠธ๋ฆผ์˜ ์„ฑ๋Šฅ์„ ๋†’์ด๋ ค๋ฉด ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ(Parallel Stream)์„ ์ ์ ˆํžˆ ํ™œ์šฉํ•ด์•ผ ํ•ด์š”.

ํ•˜์ง€๋งŒ ๋ฌด์กฐ๊ฑด ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ์ด ์ข‹์€ ๊ฑด ์•„๋‹ˆ์—์š”! ์„ฑ๋Šฅ ์ฐจ์ด๋ฅผ ์ง์ ‘ ๋น„๊ตํ•ด๋ณผ๊นŒ์š”?

๐Ÿ’ก ์˜ˆ์ œ: 1๋ถ€ํ„ฐ 10,000,000๊นŒ์ง€ ์ˆซ์ž๋ฅผ ๋”ํ•˜๋Š” ์—ฐ์‚ฐ

import java.util.stream.IntStream;

public class StreamPerformanceTest {
    public static void main(String[] args) {
        long start, end;

        // 1๏ธโƒฃ ์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ
        start = System.nanoTime();
        int sequentialSum = IntStream.rangeClosed(1, 10_000_000).sum();
        end = System.nanoTime();
        System.out.println("์ˆœ์ฐจ ์ŠคํŠธ๋ฆผ ์‹คํ–‰ ์‹œ๊ฐ„: " + (end - start) / 1_000_000 + "ms");

        // 2๏ธโƒฃ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ
        start = System.nanoTime();
        int parallelSum = IntStream.rangeClosed(1, 10_000_000).parallel().sum();
        end = System.nanoTime();
        System.out.println("๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์‹คํ–‰ ์‹œ๊ฐ„: " + (end - start) / 1_000_000 + "ms");
    }
}

โœ… ๊ฒฐ๊ณผ:

๐Ÿ“Œ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์‚ฌ์šฉ์ด ์œ ๋ฆฌํ•œ ๊ฒฝ์šฐ

โœ” ๋ฐ์ดํ„ฐ ํฌ๊ธฐ๊ฐ€ ํฌ๊ณ , ์—ฐ์‚ฐ์ด ๋ณต์žกํ•  ๋•Œ

โœ” I/O ์ž‘์—…์ด ์—†๊ณ , CPU ์—ฐ์‚ฐ์ด ๋งŽ์„ ๋•Œ

โœ” ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜์ง€ ์•Š์€ ๊ฒฝ์šฐ

๐Ÿ“Œ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์‚ฌ์šฉ์ด ๋ถˆ๋ฆฌํ•œ ๊ฒฝ์šฐ

โŒ ๋ฐ์ดํ„ฐ ๊ฐœ์ˆ˜๊ฐ€ ์ ์„ ๋•Œ (๋ณ‘๋ ฌํ™” ์˜ค๋ฒ„ํ—ค๋“œ ๋ฐœ์ƒ)

โŒ ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•œ ๊ฒฝ์šฐ (๊ฒฐ๊ณผ๊ฐ€ ๋’ค์„ž์ผ ์ˆ˜ ์žˆ์Œ)

โŒ ๊ณต์œ  ์ž์›์„ ์‚ฌ์šฉํ•  ๋•Œ (๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ๋ฌธ์ œ ๋ฐœ์ƒ ๊ฐ€๋Šฅ)

2๏ธโƒฃ ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ ์ตœ์ ํ™” - ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ ์ค„์ด๊ธฐ

์ŠคํŠธ๋ฆผ์˜ ์—ฐ์‚ฐ ์ˆœ์„œ๋ฅผ ๋ฐ”๊พธ๋ฉด ์„ฑ๋Šฅ์„ ํฌ๊ฒŒ ํ–ฅ์ƒํ•  ์ˆ˜ ์žˆ์–ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: ์ตœ์ ํ™” ์ „ํ›„ ๋น„๊ต

๐Ÿ”ด ๋น„ํšจ์œจ์ ์ธ ์ฝ”๋“œ (๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ ๋ฐœ์ƒ!)

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

List<String> result = names.stream()
    .map(String::toUpperCase)  // โŒ ๋ชจ๋“  ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ€ํ™˜ ํ›„ ํ•„ํ„ฐ๋ง (๋น„ํšจ์œจ์ !)
    .filter(name -> name.startsWith("A"))
    .collect(Collectors.toList());

๐ŸŸข ์ตœ์ ํ™”๋œ ์ฝ”๋“œ (๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ ์ œ๊ฑฐ!)

List<String> result = names.stream()
    .filter(name -> name.startsWith("A"))  // โœ… ๋จผ์ € ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋งŒ ๋‚จ๊น€
    .map(String::toUpperCase)
    .collect(Collectors.toList());

โœ” ๋ถˆํ•„์š”ํ•œ ๋ณ€ํ™˜ ์—ฐ์‚ฐ์„ ์ค„์ด๋ฉด ์†๋„๊ฐ€ ๋” ๋นจ๋ผ์ ธ์š”!


3๏ธโƒฃ ์ŠคํŠธ๋ฆผ ์„ฑ๋Šฅ ์ธก์ • & ๋””๋ฒ„๊น…

์ŠคํŠธ๋ฆผ์˜ ์„ฑ๋Šฅ์„ ์ธก์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณผ๊นŒ์š”?

๐Ÿ’ก ์˜ˆ์ œ: System.nanoTime()์„ ํ™œ์šฉํ•œ ์„ฑ๋Šฅ ์ธก์ •

long start = System.nanoTime();

List<Integer> numbers = IntStream.range(1, 1_000_000)
    .boxed()
    .collect(Collectors.toList());

long end = System.nanoTime();
System.out.println("์ŠคํŠธ๋ฆผ ์‹คํ–‰ ์‹œ๊ฐ„: " + (end - start) / 1_000_000 + "ms");

โœ… ์ŠคํŠธ๋ฆผ์˜ ์„ฑ๋Šฅ์„ ์ง์ ‘ ์ธก์ •ํ•˜๊ณ , ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์–ด์š”!


๐Ÿ”Ÿ+3 13๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์„ ๋Œ€์ฒดํ•˜๋Š” ์ตœ์‹  ๊ธฐ์ˆ 

์ŠคํŠธ๋ฆผ์€ ๊ฐ•๋ ฅํ•˜์ง€๋งŒ, ๋” ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ธ ์ตœ์‹  ๊ธฐ์ˆ ๋“ค์ด ์žˆ์–ด์š”!

์ด์ œ ์ŠคํŠธ๋ฆผ๊ณผ ๋น„๊ตํ•  ์ˆ˜ ์žˆ๋Š” ์ตœ์‹  ๋Œ€์ฒด ๊ธฐ์ˆ ์„ ์•Œ์•„๋ณผ๊ฒŒ์š”.


1๏ธโƒฃ Loom (๊ฐ€๋ฒผ์šด ์Šค๋ ˆ๋“œ)๋ฅผ ํ™œ์šฉํ•œ ๋Œ€์ฒด ๊ธฐ์ˆ 

Java 21๋ถ€ํ„ฐ ๊ฐ€๋ฒผ์šด ์Šค๋ ˆ๋“œ(Virtual Thread, Project Loom) ๊ฐ€ ๋“ฑ์žฅํ–ˆ์–ด์š”!

์ด์ œ ์ŠคํŠธ๋ฆผ ๋Œ€์‹  ๋ณ‘๋ ฌ ์‹คํ–‰์„ ๋” ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ’ก ์˜ˆ์ œ: Virtual Thread๋ฅผ ํ™œ์šฉํ•œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ

import java.util.concurrent.Executors;
import java.util.stream.IntStream;

public class LoomExample {
    public static void main(String[] args) {
        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            IntStream.range(1, 10).forEach(i ->
                executor.submit(() -> System.out.println("Task " + i + " ์‹คํ–‰ ์ค‘!"))
            );
        }
    }
}

โœ… ์ด์ œ parallelStream() ์—†์ด๋„ ๊ฐ€๋ณ๊ฒŒ ๋ณ‘๋ ฌ ์‹คํ–‰์ด ๊ฐ€๋Šฅํ•ด์š”!


2๏ธโƒฃ Reactive Streams (Spring WebFlux) ํ™œ์šฉ

์ŠคํŠธ๋ฆผ์€ ๋™๊ธฐ ์ฒ˜๋ฆฌ์ง€๋งŒ, Spring WebFlux๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋น„๋™๊ธฐ ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: WebClient๋กœ ๋น„๋™๊ธฐ API ์‘๋‹ต ์ฒ˜๋ฆฌ

import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Flux;

public class ReactiveStreamExample {
    public static void main(String[] args) {
        WebClient client = WebClient.create("https://jsonplaceholder.typicode.com");

        Flux<String> userNames = client.get()
                .uri("/users")
                .retrieve()
                .bodyToFlux(User.class)
                .map(User::getName);

        userNames.subscribe(System.out::println); // ๋น„๋™๊ธฐ ์‹คํ–‰!
    }
}

โœ… ๋น„๋™๊ธฐ ๋ฐฉ์‹์œผ๋กœ API ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์–ด์š”!


๐ŸŽฏ 12~13๋‹จ๊ณ„ ์š”์•ฝ

โœ… ์ŠคํŠธ๋ฆผ ์„ฑ๋Šฅ ์ตœ์ ํ™” (๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ๋น„๊ต, ๋ถˆํ•„์š”ํ•œ ์—ฐ์‚ฐ ์ค„์ด๊ธฐ)

โœ… ์ŠคํŠธ๋ฆผ ์‹คํ–‰ ์†๋„ ์ธก์ • (System.nanoTime() ํ™œ์šฉ)

โœ… ์ตœ์‹  ๋Œ€์ฒด ๊ธฐ์ˆ  ๋น„๊ต (Virtual Thread, Reactive Streams)


#


๐Ÿ”Ÿ+4 14๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์˜ ๊ณ ๊ธ‰ ํŒจํ„ด & ๋Œ€๊ธฐ์—…์—์„œ ํ™œ์šฉํ•˜๋Š” ๊ธฐ๋ฒ•

์ด ๋‹จ๊ณ„์—์„œ๋Š” ์‹ค๋ฌด์—์„œ ๊ณ ๊ธ‰ ๊ฐœ๋ฐœ์ž๋“ค์ด ์‚ฌ์šฉํ•˜๋Š” ์ŠคํŠธ๋ฆผ ํ™œ์šฉ ํŒจํ„ด์„ ๋ฐฐ์šธ ๊ฑฐ์˜ˆ์š”.


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ + ๋””์ž์ธ ํŒจํ„ด ํ™œ์šฉํ•˜๊ธฐ

๐Ÿ“Œ 1. ์ŠคํŠธ๋ฆผ + ์ „๋žต ํŒจํ„ด (Strategy Pattern)

๐Ÿ’ก ์˜ˆ์ œ: ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ• ์ธ ์ „๋žต์„ ์ ์šฉํ•˜๋Š” ์ฝ”๋“œ

interface DiscountStrategy {
    double applyDiscount(double price);
}

// ์ „๋žต 1: 10% ํ• ์ธ
class TenPercentDiscount implements DiscountStrategy {
    public double applyDiscount(double price) {
        return price * 0.9;
    }
}

// ์ „๋žต 2: 5000์› ํ• ์ธ
class FixedDiscount implements DiscountStrategy {
    public double applyDiscount(double price) {
        return price - 5000;
    }
}

public class StreamStrategyExample {
    public static void main(String[] args) {
        List<Double> prices = List.of(10000.0, 20000.0, 30000.0);

        List<Double> discountedPrices = prices.stream()
            .map(price -> new TenPercentDiscount().applyDiscount(price))
            .collect(Collectors.toList());

        System.out.println(discountedPrices); // [9000.0, 18000.0, 27000.0]
    }
}

โœ… ์ŠคํŠธ๋ฆผ๊ณผ ์ „๋žต ํŒจํ„ด์„ ๊ฒฐํ•ฉํ•˜๋ฉด ๋” ์œ ์—ฐํ•œ ์ฝ”๋“œ ์ž‘์„ฑ ๊ฐ€๋Šฅ!


๐Ÿ“Œ 2. ์ŠคํŠธ๋ฆผ + ํŒฉํ† ๋ฆฌ ํŒจํ„ด (Factory Pattern)

๐Ÿ’ก ์˜ˆ์ œ: JSON, XML, CSV ํŒŒ์ผ์„ ๋‹ค๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ์ฝ”๋“œ

interface FileParser {
    void parse(String data);
}

class JsonParser implements FileParser {
    public void parse(String data) {
        System.out.println("JSON ํŒŒ์‹ฑ: " + data);
    }
}

class CsvParser implements FileParser {
    public void parse(String data) {
        System.out.println("CSV ํŒŒ์‹ฑ: " + data);
    }
}

class ParserFactory {
    public static FileParser getParser(String type) {
        return switch (type.toLowerCase()) {
            case "json" -> new JsonParser();
            case "csv" -> new CsvParser();
            default -> throw new IllegalArgumentException("์ง€์›ํ•˜์ง€ ์•Š๋Š” ํ˜•์‹");
        };
    }
}

public class StreamFactoryExample {
    public static void main(String[] args) {
        List<String> fileTypes = List.of("json", "csv");

        fileTypes.stream()
            .map(ParserFactory::getParser)
            .forEach(parser -> parser.parse("๋ฐ์ดํ„ฐ"));
    }
}

โœ… ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜๋ฉด ์—ฌ๋Ÿฌ ๊ฐœ์˜ ํŒŒ์ผ ํ˜•์‹์„ ๋™์ ์œผ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์Œ!


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ (๋ฐฐ์น˜ ์‹œ์Šคํ…œ ์ ์šฉ)

๋Œ€๊ธฐ์—…์—์„œ๋Š” ์ˆ˜๋ฐฑ๋งŒ ๊ฑด์˜ ๋ฐ์ดํ„ฐ๋ฅผ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์•„์š”.

์ด๋Ÿด ๋•Œ ์ŠคํŠธ๋ฆผ + ๋ฐฐ์น˜(Batch) ์ฒ˜๋ฆฌ ํŒจํ„ด์„ ํ™œ์šฉํ•˜๋ฉด ์ข‹์•„์š”!

๐Ÿ’ก ์˜ˆ์ œ: 10,000๊ฐœ์˜ ๋ฐ์ดํ„ฐ๋ฅผ 100๊ฐœ์”ฉ ๋‚˜๋ˆ„์–ด ์ฒ˜๋ฆฌ

import java.util.stream.IntStream;
import java.util.List;

public class BatchProcessingExample {
    public static void main(String[] args) {
        List<Integer> numbers = IntStream.rangeClosed(1, 10_000).boxed().toList();
        int batchSize = 100;

        IntStream.range(0, (numbers.size() + batchSize - 1) / batchSize)
            .mapToObj(i -> numbers.subList(i * batchSize, Math.min(numbers.size(), (i + 1) * batchSize)))
            .forEach(batch -> {
                System.out.println("์ฒ˜๋ฆฌ ์ค‘: " + batch);
                // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์ €์žฅ, API ํ˜ธ์ถœ ๋“ฑ์˜ ์ž‘์—… ์ˆ˜ํ–‰
            });
    }
}

โœ… ๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ๋‚˜๋ˆ ์„œ(batch) ์ฒ˜๋ฆฌํ•˜๋ฉด ์†๋„์™€ ์„ฑ๋Šฅ์ด ๊ฐœ์„ ๋จ!


3๏ธโƒฃ ์ตœ์‹  Java ๊ธฐ๋Šฅ ํ™œ์šฉ (Record + Stream ๊ฒฐํ•ฉ)

Java 14๋ถ€ํ„ฐ ๋„์ž…๋œ record๋Š” ๋ถˆ๋ณ€ ๋ฐ์ดํ„ฐ ๊ฐ์ฒด๋ฅผ ์‰ฝ๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด์—์š”.

์ŠคํŠธ๋ฆผ๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ๋” ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: record๋ฅผ ํ™œ์šฉํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

record Product(String name, double price) {}

public class StreamRecordExample {
    public static void main(String[] args) {
        List<Product> products = List.of(
            new Product("๋…ธํŠธ๋ถ", 1500000),
            new Product("์Šค๋งˆํŠธํฐ", 1000000),
            new Product("ํƒœ๋ธ”๋ฆฟ", 800000)
        );

        double totalPrice = products.stream()
            .mapToDouble(Product::price)
            .sum();

        System.out.println("์ด ๊ฐ€๊ฒฉ: " + totalPrice);
    }
}

โœ… ๋ถˆ๋ณ€ ๊ฐ์ฒด record์™€ ์ŠคํŠธ๋ฆผ์„ ๊ฒฐํ•ฉํ•˜๋ฉด ๋” ์•ˆ์ •์ ์ธ ์ฝ”๋“œ ์ž‘์„ฑ ๊ฐ€๋Šฅ!

๐Ÿ”Ÿ+5 15๋‹จ๊ณ„: ๋ฏธ๋ž˜์˜ ์ŠคํŠธ๋ฆผ (์ตœ์‹  ๊ธฐ์ˆ  ํŠธ๋ Œ๋“œ ์ ์šฉ)

๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฏธ๋ž˜์—๋Š” ์ŠคํŠธ๋ฆผ์ด ์–ด๋–ป๊ฒŒ ๋ฐœ์ „ํ• ์ง€๋ฅผ ์‚ดํŽด๋ณผ๊ฒŒ์š”!

1๏ธโƒฃ Java 21 ์ดํ›„์˜ ์ŠคํŠธ๋ฆผ ๋ณ€ํ™”

โœ… Virtual Threads (๊ฐ€์ƒ ์Šค๋ ˆ๋“œ) ๋„์ž…

โœ… Structured Concurrency ๋„์ž…


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ์„ ๋Œ€์ฒดํ•˜๋Š” ๊ธฐ์ˆ  ํŠธ๋ Œ๋“œ

๊ธฐ์ˆ  ์„ค๋ช… ์ŠคํŠธ๋ฆผ๊ณผ ๋น„๊ต
Project Loom (Virtual Threads) ๊ฐ€๋ฒผ์šด ์Šค๋ ˆ๋“œ ๊ธฐ๋ฐ˜ ๋น„๋™๊ธฐ ์ฒ˜๋ฆฌ parallelStream()๋ณด๋‹ค ๋” ์œ ์—ฐํ•จ
Reactive Streams (Spring WebFlux) ๋น„๋™๊ธฐ ์ŠคํŠธ๋ฆผ ์ฒ˜๋ฆฌ ์ผ๋ฐ˜ ์ŠคํŠธ๋ฆผ๋ณด๋‹ค ๋” ๋น ๋ฆ„
Kotlin Coroutines ๋น„๋™๊ธฐ ์ž‘์—… ์ตœ์ ํ™” Java ์ŠคํŠธ๋ฆผ๋ณด๋‹ค ๋” ํšจ์œจ์ 

๐Ÿ“Œ ์•ž์œผ๋กœ๋Š” Stream๊ณผ Virtual Thread, Reactive Streams๋ฅผ ํ•จ๊ป˜ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ค‘์š”ํ•ด์งˆ ๊ฑฐ์˜ˆ์š”!


๐ŸŽฏ 14~15๋‹จ๊ณ„ ์š”์•ฝ

โœ… ์ŠคํŠธ๋ฆผ + ๋””์ž์ธ ํŒจํ„ด (์ „๋žต ํŒจํ„ด, ํŒฉํ† ๋ฆฌ ํŒจํ„ด ์ ์šฉ)

โœ… ๋Œ€๊ธฐ์—…์—์„œ ์“ฐ๋Š” ๋ฐฐ์น˜ ์‹œ์Šคํ…œ (๋Œ€์šฉ๋Ÿ‰ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์ตœ์ ํ™”)

โœ… ์ตœ์‹  Java ๊ธฐ๋Šฅ (record + Stream ๊ฒฐํ•ฉ) ํ™œ์šฉ

โœ… ๋ฏธ๋ž˜์˜ ์ŠคํŠธ๋ฆผ (Project Loom, Reactive Streams, Kotlin Coroutines ์ ์šฉ ๊ฐ€๋Šฅ์„ฑ)



๐Ÿ”Ÿ+6 16๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ์ฐฝ์˜์ ์ธ ๋ฌธ์ œ ํ•ด๊ฒฐ

์ด ๋‹จ๊ณ„์—์„œ๋Š” ์ŠคํŠธ๋ฆผ์„ ์ฐฝ์˜์ ์œผ๋กœ ํ™œ์šฉํ•˜์—ฌ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šธ ๊ฑฐ์˜ˆ์š”.


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ•ด๊ฒฐ

์ŠคํŠธ๋ฆผ์„ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ•ด๊ฒฐ์— ํ™œ์šฉํ•˜๋ฉด ์ฝ”๋“œ๋ฅผ ๋” ๊ฐ„๊ฒฐํ•˜๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์–ด์š”!

์ž์ฃผ ๋‚˜์˜ค๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ํ•ด๊ฒฐํ•ด ๋ณผ๊นŒ์š”?

๐Ÿ“Œ 1. ๋ฐฐ์—ด์—์„œ ๋‘ ์ˆซ์ž์˜ ํ•ฉ์ด ํŠน์ • ๊ฐ’์ด ๋˜๋Š” ๊ฒฝ์šฐ ์ฐพ๊ธฐ

๐Ÿ’ก ์˜ˆ์ œ: ๋ฆฌ์ŠคํŠธ์—์„œ ๋‘ ์ˆซ์ž์˜ ํ•ฉ์ด 10์ด ๋˜๋Š” ์Œ ์ฐพ๊ธฐ

import java.util.*;
import java.util.stream.Collectors;

public class TwoSumStream {
    public static void main(String[] args) {
        List<Integer> numbers = List.of(1, 2, 3, 7, 8, 9, 10);

        Set<Integer> seen = new HashSet<>();

        List<List<Integer>> result = numbers.stream()
            .filter(n -> {
                if (seen.contains(10 - n)) return true;
                seen.add(n);
                return false;
            })
            .map(n -> List.of(n, 10 - n))
            .collect(Collectors.toList());

        System.out.println(result); // [[7, 3], [8, 2], [9, 1]]
    }
}

โœ… ์ด์ œ for ๋ฌธ ์—†์ด๋„ ๋‘ ์ˆซ์ž์˜ ํ•ฉ์„ ์ฐพ๋Š” ๋กœ์ง์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Œ!


๐Ÿ“Œ 2. ๊ฐ€์žฅ ๋งŽ์ด ๋“ฑ์žฅํ•œ ๋‹จ์–ด ์ฐพ๊ธฐ

๐Ÿ’ก ์˜ˆ์ œ: ๋ฌธ์žฅ์—์„œ ๊ฐ€์žฅ ๋งŽ์ด ๋“ฑ์žฅํ•˜๋Š” ๋‹จ์–ด ์ฐพ๊ธฐ

import java.util.*;
import java.util.stream.Collectors;

public class MostFrequentWord {
    public static void main(String[] args) {
        String text = "Java Stream Stream Java Functional Programming Java";

        String mostFrequentWord = Arrays.stream(text.split(" "))
            .collect(Collectors.groupingBy(word -> word, Collectors.counting()))
            .entrySet()
            .stream()
            .max(Map.Entry.comparingByValue()) // ๊ฐ€์žฅ ๋งŽ์ด ๋“ฑ์žฅํ•œ ๋‹จ์–ด ์ฐพ๊ธฐ
            .map(Map.Entry::getKey)
            .orElse("");

        System.out.println("๊ฐ€์žฅ ๋งŽ์ด ๋“ฑ์žฅํ•œ ๋‹จ์–ด: " + mostFrequentWord); // Java
    }
}

โœ… ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜๋ฉด ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์œผ๋กœ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Œ!


๐Ÿ“Œ 3. ํŒ”๋ฆฐ๋“œ๋กฌ(ํšŒ๋ฌธ) ์ฒดํฌํ•˜๊ธฐ

๐Ÿ’ก ์˜ˆ์ œ: โ€œracecarโ€ ๊ฐ™์€ ๋ฌธ์ž์—ด์ด ํšŒ๋ฌธ์ธ์ง€ ํ™•์ธ

import java.util.stream.IntStream;

public class PalindromeCheck {
    public static void main(String[] args) {
        String word = "racecar";

        boolean isPalindrome = IntStream.range(0, word.length() / 2)
            .allMatch(i -> word.charAt(i) == word.charAt(word.length() - i - 1));

        System.out.println("ํšŒ๋ฌธ ์—ฌ๋ถ€: " + isPalindrome); // true
    }
}

โœ… ๊ธฐ์กด for ๋ฌธ๋ณด๋‹ค ํ›จ์”ฌ ๊ฐ„๊ฒฐํ•œ ์ฝ”๋“œ๋กœ ํšŒ๋ฌธ ์—ฌ๋ถ€๋ฅผ ์ฒดํฌํ•  ์ˆ˜ ์žˆ์Œ!


๐Ÿ”Ÿ+7 17๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ๊ณผ ๋‹ค๋ฅธ ํŒจ๋Ÿฌ๋‹ค์ž„ ๋น„๊ต

์ŠคํŠธ๋ฆผ๊ณผ ๋‹ค๋ฅธ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„(ํ•จ์ˆ˜ํ˜•, ๋ฆฌ์•กํ‹ฐ๋ธŒ, ๋ณ‘๋ ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋“ฑ)์„ ๋น„๊ตํ•˜๋ฉฐ ์ŠคํŠธ๋ฆผ์˜ ํ•œ๊ณ„๋ฅผ ์ดํ•ดํ•˜๋Š” ๋‹จ๊ณ„์˜ˆ์š”!


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ vs ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ (Kotlin, Scala ๋น„๊ต)

์ž๋ฐ” ์ŠคํŠธ๋ฆผ์€ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ(FP)์˜ ์ผ๋ถ€์ง€๋งŒ, ์™„์ „ํ•œ FP ์Šคํƒ€์ผ์€ ์•„๋‹ˆ์—์š”.

Kotlin๊ณผ Scala ๊ฐ™์€ ์–ธ์–ด์—์„œ๋Š” ๋” ๊ฐ•๋ ฅํ•œ FP ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ด์š”.

โœ… ๋žŒ๋‹ค ํ‘œํ˜„์‹ ๋น„๊ต (Kotlin vs Java)

๊ธฐ๋Šฅ Java Kotlin
๋ฆฌ์ŠคํŠธ ๋ณ€ํ™˜ list.stream().map(n -> n * 2).collect(Collectors.toList()) list.map { it * 2 }
ํ•„ํ„ฐ๋ง list.stream().filter(n -> n > 10).collect(Collectors.toList()) list.filter { it > 10 }
์ง‘๊ณ„ list.stream().count() list.count()

๐Ÿ“Œ Kotlin์˜ FP ์Šคํƒ€์ผ์ด ์ž๋ฐ” ์ŠคํŠธ๋ฆผ๋ณด๋‹ค ๋” ๊ฐ„๊ฒฐํ•œ ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์Œ!

๐Ÿ“Œ ํ•˜์ง€๋งŒ ์ž๋ฐ”๋Š” ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ํ™˜๊ฒฝ์—์„œ ์•ˆ์ •์„ฑ์ด ๋†’์•„ ๋งŽ์ด ์‚ฌ์šฉ๋จ!


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ vs ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ (RxJava, Reactor)

๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ์ŠคํŠธ๋ฆผ๊ณผ ์œ ์‚ฌํ•˜์ง€๋งŒ, ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ํ๋ฆ„์„ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ์Œ!

โœ… ์ŠคํŠธ๋ฆผ vs ๋ฆฌ์•กํ‹ฐ๋ธŒ ๋น„๊ต

๊ธฐ๋Šฅ Java Stream Reactive Stream (RxJava, Reactor)
๋™๊ธฐ ์ฒ˜๋ฆฌ โœ… ๊ฐ€๋Šฅ โŒ ๋น„๋™๊ธฐ
๋น„๋™๊ธฐ ์ด๋ฒคํŠธ ์ฒ˜๋ฆฌ โŒ ๋ถˆ๊ฐ€๋Šฅ โœ… ๊ฐ€๋Šฅ
๋ฐ์ดํ„ฐ ํ๋ฆ„ ์ œ์–ด โŒ ๋ถˆ๊ฐ€๋Šฅ โœ… ๊ฐ€๋Šฅ (backpressure ์ง€์›)

๐Ÿ“Œ ์ŠคํŠธ๋ฆผ์€ ๋™๊ธฐ ๋ฐ์ดํ„ฐ ํ๋ฆ„, ๋ฆฌ์•กํ‹ฐ๋ธŒ๋Š” ๋น„๋™๊ธฐ ๋ฐ์ดํ„ฐ ํ๋ฆ„!

๐Ÿ“Œ API ์‘๋‹ต์„ ๋น ๋ฅด๊ฒŒ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค๋ฉด WebFlux ๊ฐ™์€ ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ์ด ๋” ์ ์ ˆ!


3๏ธโƒฃ ์ŠคํŠธ๋ฆผ vs ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ (Thread & Executor ๋น„๊ต)

๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•  ๋•Œ parallelStream()์„ ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ง์ ‘ Thread๋‚˜ ExecutorService๋ฅผ ํ™œ์šฉํ•  ์ˆ˜๋„ ์žˆ์–ด์š”.

โœ… ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ

โœ” ๋ฐ์ดํ„ฐ๊ฐ€ ํฌ๊ณ , CPU ์—ฐ์‚ฐ์ด ๋งŽ์„ ๋•Œ

โœ” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋„คํŠธ์›Œํฌ ์š”์ฒญ์„ ๋™์‹œ์— ๋ณด๋‚ผ ๋•Œ

โœ” ๋ณต์žกํ•œ ๋น„๋™๊ธฐ ๋กœ์ง์„ ์ฒ˜๋ฆฌํ•  ๋•Œ

๐Ÿ’ก ์˜ˆ์ œ: ExecutorService๋ฅผ ํ™œ์šฉํ•œ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.IntStream;

public class ExecutorExample {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(4);

        IntStream.range(1, 10)
            .forEach(i -> executor.submit(() -> System.out.println("Task " + i + " ์‹คํ–‰ ์ค‘!")));

        executor.shutdown();
    }
}

โœ… ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ parallelStream()๋ณด๋‹ค ExecutorService๊ฐ€ ๋” ์œ ๋ฆฌํ•  ์ˆ˜๋„ ์žˆ์Œ!


๐ŸŽฏ 16~17๋‹จ๊ณ„ ์š”์•ฝ

โœ… ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ์•Œ๊ณ ๋ฆฌ์ฆ˜ ๋ฌธ์ œ ํ•ด๊ฒฐ (๋‘ ์ˆ˜ ํ•ฉ, ๊ฐ€์žฅ ๋งŽ์ด ๋“ฑ์žฅํ•œ ๋‹จ์–ด, ํšŒ๋ฌธ ์ฒดํฌ)

โœ… ์ŠคํŠธ๋ฆผ vs ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ (Kotlin, Scala ๋น„๊ต)

โœ… ์ŠคํŠธ๋ฆผ vs ๋ฆฌ์•กํ‹ฐ๋ธŒ ์ŠคํŠธ๋ฆผ (RxJava, Reactor ๋น„๊ต)

โœ… ์ŠคํŠธ๋ฆผ vs ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ (parallelStream vs ExecutorService ๋น„๊ต)



๐Ÿ”Ÿ+8 18๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์„ ์ด์šฉํ•œ ์ฝ”๋“œ ํ’ˆ์งˆ ํ–ฅ์ƒ & ์œ ์ง€๋ณด์ˆ˜์„ฑ ๋†’์ด๊ธฐ

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


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•  ๋•Œ์˜ ์•ˆํ‹ฐํŒจํ„ด (์ž˜๋ชป๋œ ์ฝ”๋“œ ์Šคํƒ€์ผ)

์ŠคํŠธ๋ฆผ์„ ์ž˜๋ชป ์‚ฌ์šฉํ•˜๋ฉด ์˜คํžˆ๋ ค ์ฝ”๋“œ๊ฐ€ ๋ณต์žกํ•ด์ง€๊ณ , ์„ฑ๋Šฅ๋„ ๋‚˜๋น ์งˆ ์ˆ˜ ์žˆ์–ด์š”.

๋‹ค์Œ๊ณผ ๊ฐ™์€ ์•ˆํ‹ฐํŒจํ„ด(Anti-Pattern)์„ ํ”ผํ•ด์•ผ ํ•ด์š”!


๐Ÿ“Œ 1. ์ŠคํŠธ๋ฆผ์„ ๋‚จ์šฉํ•˜๋Š” ๊ฒฝ์šฐ

โŒ ๋น„ํšจ์œจ์ ์ธ ์ฝ”๋“œ (์ŠคํŠธ๋ฆผ์„ ๋‚จ์šฉํ•˜๋ฉด ๊ฐ€๋…์„ฑ์ด ๋‚˜๋น ์ง!)

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

// ๋„ˆ๋ฌด ๋ณต์žกํ•œ ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ (๊ฐ€๋…์„ฑ ์ €ํ•˜)
List<String> result = names.stream()
    .map(String::toUpperCase)
    .filter(name -> name.startsWith("A"))
    .sorted()
    .limit(1)
    .collect(Collectors.toList());

โœ” ๊ฐœ์„ ๋œ ์ฝ”๋“œ (๊ฐ€๋…์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด ๋ณ€์ˆ˜๋กœ ๋ถ„๋ฆฌ!)

Stream<String> nameStream = names.stream().map(String::toUpperCase);
Stream<String> filteredStream = nameStream.filter(name -> name.startsWith("A"));
Stream<String> sortedStream = filteredStream.sorted();
List<String> result = sortedStream.limit(1).collect(Collectors.toList());

โœ… ์ŠคํŠธ๋ฆผ์„ ํ•œ ์ค„์— ๋„ˆ๋ฌด ๋งŽ์ด ์“ฐ์ง€ ๋ง๊ณ , ๊ฐ€๋…์„ฑ์„ ๊ณ ๋ คํ•˜์—ฌ ๋ถ„๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ!


๐Ÿ“Œ 2. forEach() ๋‚จ์šฉ

โŒ ์ž˜๋ชป๋œ ์‚ฌ์šฉ๋ฒ• (forEach()๋ฅผ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์— ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋จ!)

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

names.stream()
    .map(name -> {
        System.out.println(name); // โŒ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์—์„œ ๋ถ€์ž‘์šฉ ๋ฐœ์ƒ
        return name.toUpperCase();
    })
    .collect(Collectors.toList());

โœ” ๊ฐœ์„ ๋œ ์ฝ”๋“œ (peek()๋ฅผ ํ™œ์šฉํ•˜๊ฑฐ๋‚˜ ์ตœ์ข… ์—ฐ์‚ฐ์—์„œ forEach() ์‚ฌ์šฉ!)

names.stream()
    .map(String::toUpperCase)
    .peek(System.out::println)  // โœ… ๋””๋ฒ„๊น…์šฉ์œผ๋กœ๋งŒ ์‚ฌ์šฉ!
    .collect(Collectors.toList());

โœ… ์ŠคํŠธ๋ฆผ์—์„œ forEach()๋Š” ์ตœ์ข… ์—ฐ์‚ฐ์—์„œ๋งŒ ์‚ฌ์šฉํ•˜๊ณ , ์ค‘๊ฐ„ ์—ฐ์‚ฐ์—์„œ๋Š” peek()๋ฅผ ํ™œ์šฉ!


๐Ÿ“Œ 3. ์„ฑ๋Šฅ ์ €ํ•˜๋ฅผ ์œ ๋ฐœํ•˜๋Š” sorted() ๋‚จ์šฉ

โŒ ์ž˜๋ชป๋œ ์‚ฌ์šฉ๋ฒ• (sorted()๋ฅผ ๋ชจ๋“  ๋ฐ์ดํ„ฐ์— ์ ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ ์ €ํ•˜!)

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

// ์ž˜๋ชป๋œ ์ฝ”๋“œ (์ „์ฒด ์ •๋ ฌ ํ›„ 3๊ฐœ๋งŒ ๊ฐ€์ ธ์˜ด)
List<Integer> result = numbers.stream()
    .sorted()  // โŒ ์ „์ฒด ์ •๋ ฌ ํ•„์š” ์—†์Œ!
    .limit(3)
    .collect(Collectors.toList());

โœ” ๊ฐœ์„ ๋œ ์ฝ”๋“œ (limit()์„ ๋จผ์ € ์ ์šฉํ•˜์—ฌ ์ •๋ ฌํ•  ๋ฐ์ดํ„ฐ ์–‘์„ ์ค„์ž„!)

List<Integer> result = numbers.stream()
    .limit(3)  // โœ… ๋จผ์ € 3๊ฐœ๋งŒ ์„ ํƒ!
    .sorted()
    .collect(Collectors.toList());

โœ… ๋ถˆํ•„์š”ํ•œ sorted() ์‚ฌ์šฉ์„ ์ค„์ด๋ฉด ์„ฑ๋Šฅ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Œ!


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ์„ ์•ˆ์ „ํ•˜๊ฒŒ ์ ์šฉํ•˜๋Š” ๋ฒ• (๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ ๊ธฐ์ค€)

์‹ค์ œ ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ๋ชจ๋“  ๊ณณ์—์„œ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋ฌด์กฐ๊ฑด ์ข‹์€ ๊ฒƒ์€ ์•„๋‹˜!

โœ… ๋‹ค์Œ ๊ธฐ์ค€์„ ์ถฉ์กฑํ•  ๋•Œ๋งŒ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Œ.

๐Ÿ“Œ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์€ ๊ฒฝ์šฐ

โœ” ๋ฐ์ดํ„ฐ ๋ณ€ํ™˜, ํ•„ํ„ฐ๋ง, ์ •๋ ฌ ๊ฐ™์€ ์ฝ๊ธฐ ์ „์šฉ ์—ฐ์‚ฐ์ด ๋งŽ์„ ๋•Œ

โœ” ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ(parallelStream())๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ์ด ๊ฐœ์„ ๋  ๋•Œ

โœ” ํ•จ์ˆ˜ํ˜• ์Šคํƒ€์ผ์ด ์ฝ”๋“œ ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์„ ๋•Œ

โŒ ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์€ ๊ฒฝ์šฐ

โŒ ๋ฃจํ”„ ๋‚ด์—์„œ ์ƒํƒœ ๋ณ€๊ฒฝ (state mutation) ์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ

โŒ ์˜ˆ์™ธ(Exception) ์ฒ˜๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ (try-catch๊ฐ€ ๋งŽ์•„์ง€๋ฉด ๊ฐ€๋…์„ฑ์ด ๋‚˜๋น ์ง)

โŒ ๋””๋ฒ„๊น…์ด ์–ด๋ ค์šด ์ฝ”๋“œ (๋ณต์žกํ•œ ์ŠคํŠธ๋ฆผ ์ฒด์ด๋‹)

๐Ÿ’ก ์˜ˆ์ œ: ์ŠคํŠธ๋ฆผ ๋Œ€์‹  for ๋ฌธ์ด ๋” ์ ์ ˆํ•œ ๊ฒฝ์šฐ

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

// โŒ ์ŠคํŠธ๋ฆผ๋ณด๋‹ค for๋ฌธ์ด ๋” ์ ์ ˆํ•œ ๊ฒฝ์šฐ (์ƒํƒœ ๋ณ€๊ฒฝ์ด ํ•„์š”ํ•  ๋•Œ)
for (int num : numbers) {
    sum += num;
}
System.out.println(sum);

โœ… ์ด๋Ÿฐ ๊ฒฝ์šฐ ์ŠคํŠธ๋ฆผ๋ณด๋‹ค for ๋ฌธ์ด ๋” ์ง๊ด€์ ์ผ ์ˆ˜ ์žˆ์Œ!


3๏ธโƒฃ ์ŠคํŠธ๋ฆผ ์ฝ”๋“œ ๋ฆฌ๋ทฐ์—์„œ ์ž์ฃผ ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ & ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ฝ”๋“œ ๋ฆฌ๋ทฐ๋ฅผ ํ†ตํ•ด ์ŠคํŠธ๋ฆผ์„ ์–ด๋–ป๊ฒŒ ์ตœ์ ํ™”ํ• ์ง€ ๊ณ ๋ฏผํ•ด์•ผ ํ•ด์š”.

๋‹ค์Œ์€ ์ฝ”๋“œ ๋ฆฌ๋ทฐ์—์„œ ์ž์ฃผ ๋‚˜์˜ค๋Š” ๋ฌธ์ œ์ ๊ณผ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์ด์—์š”!

๐Ÿ“Œ 1. ๋ถˆํ•„์š”ํ•œ collect() ํ˜ธ์ถœ

โŒ ์ž˜๋ชป๋œ ์ฝ”๋“œ (๊ตณ์ด ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜ ํ›„ ๋‹ค์‹œ ์ŠคํŠธ๋ฆผ ์‚ฌ์šฉ!)

jList<String> filteredNames = names.stream()
    .filter(name -> name.startsWith("A"))
    .collect(Collectors.toList())  // โŒ ๋ถˆํ•„์š”ํ•œ ๋ฆฌ์ŠคํŠธ ๋ณ€ํ™˜
    .stream()
    .map(String::toUpperCase)
    .collect(Collectors.toList());

โœ” ๊ฐœ์„ ๋œ ์ฝ”๋“œ (์—ฐ์†๋œ ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ์„ ์œ ์ง€!)

List<String> filteredNames = names.stream()
    .filter(name -> name.startsWith("A"))
    .map(String::toUpperCase)
    .collect(Collectors.toList());

โœ… ์ŠคํŠธ๋ฆผ์„ ํ•œ ๋ฒˆ๋งŒ ์‚ฌ์šฉํ•˜๊ณ , ์ค‘๊ฐ„์— collect()๋ฅผ ์“ฐ์ง€ ์•Š๋Š” ๊ฒƒ์ด ์ข‹์Œ!


๐Ÿ“Œ 2. Optional์„ ํ™œ์šฉํ•œ ์•ˆ์ „ํ•œ ์ฝ”๋“œ ์ž‘์„ฑ

์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•  ๋•Œ NullPointerException (NPE) ๋ฐฉ์ง€๋ฅผ ์œ„ํ•ด Optional์„ ์ ๊ทน ํ™œ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์•„์š”!

๐Ÿ’ก ์˜ˆ์ œ: ๊ฐ€์žฅ ๊ธด ๋ฌธ์ž์—ด ์ฐพ๊ธฐ (Optional ํ™œ์šฉ)

Optional<String> longestWord = names.stream()
    .max(Comparator.comparingInt(String::length));

longestWord.ifPresent(System.out::println);  // ๊ฐ’์ด ์žˆ์œผ๋ฉด ์ถœ๋ ฅ!

โœ… ์ด์ œ NullPointerException ๊ฑฑ์ • ์—†์ด ์•ˆ์ „ํ•œ ์ฝ”๋“œ ์ž‘์„ฑ ๊ฐ€๋Šฅ!


๐ŸŽฏ 18๋‹จ๊ณ„ ์š”์•ฝ

โœ… ์ŠคํŠธ๋ฆผ ์•ˆํ‹ฐํŒจํ„ด (๋‚จ์šฉํ•˜์ง€ ์•Š๊ธฐ, forEach() & sorted() ์ฃผ์˜)

โœ… ๋Œ€๊ทœ๋ชจ ํ”„๋กœ์ ํŠธ์—์„œ ์ŠคํŠธ๋ฆผ์„ ์–ธ์ œ ์‚ฌ์šฉํ• ์ง€ ํŒ๋‹จํ•˜๋Š” ๊ธฐ์ค€

โœ… ์ฝ”๋“œ ๋ฆฌ๋ทฐ์—์„œ ์ž์ฃผ ๋‚˜์˜ค๋Š” ์ŠคํŠธ๋ฆผ ์ตœ์ ํ™” ๋ฌธ์ œ ํ•ด๊ฒฐ๋ฒ•

โœ… Optional์„ ํ™œ์šฉํ•˜์—ฌ ์•ˆ์ „ํ•œ ์ŠคํŠธ๋ฆผ ์ฝ”๋“œ ์ž‘์„ฑํ•˜๊ธฐ


๐ŸŽ‰ ์ž๋ฐ” ์ŠคํŠธ๋ฆผ ์™„๋ฒฝ ๋งˆ์Šคํ„ฐ - ๋ํŒ์™• ๋‹จ๊ณ„!

โœ… ์ŠคํŠธ๋ฆผ์˜ ๊ธฐ๋ณธ ๊ฐœ๋…๋ถ€ํ„ฐ ์ตœ์‹  ๊ธฐ์ˆ  ์ ์šฉ๊นŒ์ง€ ์ „๋ถ€ ํ•™์Šต ์™„๋ฃŒ!

โœ… ์‹ค์ „ ํ”„๋กœ์ ํŠธ์—์„œ ์ŠคํŠธ๋ฆผ์„ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ ์šฉํ•˜๋Š” ๊ธฐ์ค€๊นŒ์ง€ ์ตํž˜!

โœ… ์ตœ์‹  Java ๊ธฐ๋Šฅ๊ณผ ์„ฑ๋Šฅ ์ตœ์ ํ™” ๊ธฐ๋ฒ•๊นŒ์ง€ ๋ฐ˜์˜ ๊ฐ€๋Šฅ!

์ด


๐Ÿ”Ÿ+9 19๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„

์ด ๋‹จ๊ณ„์—์„œ๋Š” ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜์—ฌ ๋Œ€๊ทœ๋ชจ ์‹œ์Šคํ…œ์„ ์„ค๊ณ„ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šธ ๊ฑฐ์˜ˆ์š”.


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ ๊ธฐ๋ฐ˜ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜ (MSA) ์„ค๊ณ„

๐Ÿ“Œ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ์˜ ํ•ต์‹ฌ ํŒจํ„ด

1๏ธโƒฃ ์ด๋ฒคํŠธ ๊ธฐ๋ฐ˜ ์•„ํ‚คํ…์ฒ˜ (Event-Driven Architecture)

2๏ธโƒฃ ๋ฐ์ดํ„ฐ ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ• (Data Pipeline)

๐Ÿ’ก ์˜ˆ์ œ: Kafka ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

import org.apache.kafka.streams.*;
import org.apache.kafka.streams.kstream.*;

import java.util.Properties;

public class KafkaStreamExample {
    public static void main(String[] args) {
        Properties props = new Properties();
        props.put(StreamsConfig.APPLICATION_ID_CONFIG, "stream-app");
        props.put(StreamsConfig.BOOTSTRAP_SERVERS_CONFIG, "localhost:9092");

        StreamsBuilder builder = new StreamsBuilder();
        KStream<String, String> stream = builder.stream("input-topic");

        stream.filter((key, value) -> value.contains("ERROR"))
              .to("error-topic");

        KafkaStreams kafkaStreams = new KafkaStreams(builder.build(), props);
        kafkaStreams.start();
    }
}

โœ… Kafka ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜๋ฉด ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง ๋ฐ ๋ผ์šฐํŒ…์ด ๊ฐ€๋Šฅ!


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ์„œ๋ฒ„๋ฆฌ์Šค(Serverless) ์•„ํ‚คํ…์ฒ˜

์ŠคํŠธ๋ฆผ์„ AWS Lambda, Google Cloud Functions ๊ฐ™์€ ์„œ๋ฒ„๋ฆฌ์Šค ํ™˜๊ฒฝ๊ณผ ๊ฒฐํ•ฉํ•˜๋ฉด ๋น„์šฉ ํšจ์œจ์ ์ธ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: AWS Lambda์—์„œ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

public class LambdaStreamHandler implements RequestHandler<List<Integer>, Integer> {
    @Override
    public Integer handleRequest(List<Integer> input, Context context) {
        return input.stream().reduce(0, Integer::sum);
    }
}

โœ… ์„œ๋ฒ„๋ฆฌ์Šค ํ™˜๊ฒฝ์—์„œ๋„ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜๋ฉด ์„ฑ๋Šฅ๊ณผ ๊ฐ€๋…์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Œ!


๐Ÿ”Ÿ+10 20๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ๋น…๋ฐ์ดํ„ฐ & AI

์ด์ œ ์ž๋ฐ” ์ŠคํŠธ๋ฆผ์„ ๋น…๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐ AI(๋จธ์‹ ๋Ÿฌ๋‹)๊ณผ ๊ฒฐํ•ฉํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ฐฐ์šธ ๊ฑฐ์˜ˆ์š”. ๐Ÿš€


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ + Apache Spark๋ฅผ ํ™œ์šฉํ•œ ๋น…๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

Apache Spark๋Š” ๋Œ€๋Ÿ‰ ๋ฐ์ดํ„ฐ๋ฅผ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ•๋ ฅํ•œ ํ”„๋ ˆ์ž„์›Œํฌ์˜ˆ์š”.

์ž๋ฐ” ์ŠคํŠธ๋ฆผ๊ณผ ๋น„์Šทํ•˜์ง€๋งŒ, ๋ถ„์‚ฐ ํ™˜๊ฒฝ์—์„œ ๋” ๊ฐ•๋ ฅํ•œ ์„ฑ๋Šฅ์„ ์ œ๊ณตํ•ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: Spark ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ์‹ค์‹œ๊ฐ„ ๋กœ๊ทธ ๋ถ„์„

import org.apache.spark.api.java.*;
import org.apache.spark.sql.*;

public class SparkStreamExample {
    public static void main(String[] args) {
        SparkSession spark = SparkSession.builder().appName("LogAnalyzer").getOrCreate();

        Dataset<Row> logs = spark.read().json("logs.json");

        logs.filter("level = 'ERROR'")
            .groupBy("message")
            .count()
            .show();
    }
}

โœ… ์ž๋ฐ” ์ŠคํŠธ๋ฆผ๊ณผ ์œ ์‚ฌํ•œ ๋ฐฉ์‹์œผ๋กœ ๋Œ€๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์Œ!


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ AI & ๋จธ์‹ ๋Ÿฌ๋‹ ์ ์šฉ

์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜๋ฉด ๋จธ์‹ ๋Ÿฌ๋‹ ๋ชจ๋ธ์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ํ•™์Šต ๋ฐ ์˜ˆ์ธกํ•˜๋Š” ์‹œ์Šคํ…œ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ์–ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ์—์„œ AI ๋ชจ๋ธ๋กœ ์˜ˆ์ธกํ•˜๊ธฐ (TensorFlow + Stream ํ™œ์šฉ)

import org.tensorflow.*;

public class TensorFlowStreamExample {
    public static void main(String[] args) {
        try (SavedModelBundle model = SavedModelBundle.load("model", "serve")) {
            Tensor<Float> input = Tensor.create(new float[]{1.0f, 2.0f, 3.0f}, Float.class);
            Tensor<Float> output = model.session().runner().feed("input", input).fetch("output").run().get(0).expect(Float.class);

            System.out.println("AI ์˜ˆ์ธก ๊ฒฐ๊ณผ: " + output.toString());
        }
    }
}

โœ… ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆผ ๋ฐ์ดํ„ฐ๋ฅผ AI ๋ชจ๋ธ๋กœ ๋ฐ”๋กœ ๋ถ„์„ ๊ฐ€๋Šฅ!


๐ŸŽฏ 19~20๋‹จ๊ณ„ ์š”์•ฝ

โœ… ์ŠคํŠธ๋ฆผ ๊ธฐ๋ฐ˜ ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜ (Kafka, Event-Driven ์‹œ์Šคํ…œ ์ ์šฉ)

โœ… ์„œ๋ฒ„๋ฆฌ์Šค ํ™˜๊ฒฝ์—์„œ ์ŠคํŠธ๋ฆผ ํ™œ์šฉ (AWS Lambda + Stream)

โœ… Apache Spark์™€ ์ŠคํŠธ๋ฆผ์„ ๊ฒฐํ•ฉํ•œ ๋น…๋ฐ์ดํ„ฐ ๋ถ„์„

โœ… AI & ๋จธ์‹ ๋Ÿฌ๋‹๊ณผ ์ŠคํŠธ๋ฆผ ๊ฒฐํ•ฉ (์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์˜ˆ์ธก ๋ชจ๋ธ ์ ์šฉ)

###


๐Ÿ”Ÿ+11 21๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ์ฐฝ์˜์  ์‹œ์Šคํ…œ ์„ค๊ณ„

์ด์ œ ์ŠคํŠธ๋ฆผ์„ ๋‹จ์ˆœํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๋„๊ตฌ๊ฐ€ ์•„๋‹ˆ๋ผ, ์•„ํ‚คํ…์ฒ˜ ์„ค๊ณ„์˜ ํ•ต์‹ฌ ์š”์†Œ๋กœ ํ™œ์šฉํ•˜๋Š” ๋ฒ•์„ ๋ฐฐ์šธ ๊ฑฐ์˜ˆ์š”.


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ ๊ธฐ๋ฐ˜์˜ ๋ถ„์‚ฐ ์‹œ์Šคํ…œ ์„ค๊ณ„

์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜๋ฉด ๋ถ„์‚ฐ ์‹œ์Šคํ…œ์„ ๋” ํšจ์œจ์ ์œผ๋กœ ์„ค๊ณ„ํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ“Œ ์˜ˆ์ œ: ์‹ค์‹œ๊ฐ„ ๊ธˆ์œต ๋ฐ์ดํ„ฐ ๋ถ„์„ ์‹œ์Šคํ…œ

๐Ÿ’ก ์˜ˆ์ œ: ๋ถ„์‚ฐ ํ™˜๊ฒฝ์—์„œ ์‹ค์‹œ๊ฐ„ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ตฌ์กฐ

KStream<String, Transaction> transactions = builder.stream("transactions");

transactions.filter((key, tx) -> tx.getAmount() > 10000)
           .to("high-value-transactions");

โœ… ์ด๋Ÿฐ ์‹œ์Šคํ…œ์„ ํ™œ์šฉํ•˜๋ฉด, ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ธˆ์œต ์‚ฌ๊ธฐ๋ฅผ ํƒ์ง€ํ•  ์ˆ˜๋„ ์žˆ์Œ!


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ + ๋ธ”๋ก์ฒด์ธ ๊ธฐ์ˆ  ๊ฒฐํ•ฉ

๐Ÿ“Œ ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•˜๋ฉด ๋ธ”๋ก์ฒด์ธ์˜ ํŠธ๋žœ์žญ์…˜์„ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ถ„์„ํ•  ์ˆ˜ ์žˆ์–ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: ๋ธ”๋ก์ฒด์ธ ํŠธ๋žœ์žญ์…˜ ์ŠคํŠธ๋ฆผ ๋ถ„์„

transactions.stream()
    .filter(tx -> tx.getValue() > 1.0) // 1 BTC ์ด์ƒ ๊ฑฐ๋ž˜ ํ•„ํ„ฐ๋ง
    .forEach(tx -> System.out.println("High-value transaction: " + tx));

โœ… ๋ธ”๋ก์ฒด์ธ ๊ธฐ์ˆ ๊ณผ ์ŠคํŠธ๋ฆผ์„ ๊ฒฐํ•ฉํ•˜๋ฉด ์ƒˆ๋กœ์šด ๊ฐ€๋Šฅ์„ฑ์ด ์—ด๋ฆผ!


3๏ธโƒฃ ์ŠคํŠธ๋ฆผ ๊ธฐ๋ฐ˜ IoT ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ

๐Ÿ“Œ IoT ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ŠคํŠธ๋ฆผ์œผ๋กœ ๋ถ„์„ํ•˜๋ฉด ์‹ค์‹œ๊ฐ„ ๋ชจ๋‹ˆํ„ฐ๋ง์ด ๊ฐ€๋Šฅํ•ด์š”!

๐Ÿ’ก ์˜ˆ์ œ: IoT ์„ผ์„œ ๋ฐ์ดํ„ฐ ์‹ค์‹œ๊ฐ„ ํ•„ํ„ฐ๋ง

sensorData.stream()
    .filter(data -> data.getTemperature() > 100) // 100๋„ ์ด์ƒ ๊ฒฝ๊ณ 
    .forEach(alertSystem::sendAlert);

โœ… ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ฉด ๊ณต์žฅ์ด๋‚˜ ์ž์œจ์ฃผํ–‰ ์‹œ์Šคํ…œ์˜ ์•ˆ์ „์„ฑ์„ ๋†’์ผ ์ˆ˜ ์žˆ์Œ!


๐Ÿ”Ÿ+12 22๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์˜ ํ•œ๊ณ„๋ฅผ ๋›ฐ์–ด๋„˜๊ธฐ ์œ„ํ•œ ์—ฐ๊ตฌ

์ด์ œ ์ŠคํŠธ๋ฆผ์„ ๋‹จ์ˆœํžˆ ๋ฐฐ์šฐ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ, ๊ฐœ์„ ํ•˜๋Š” ์ž…์žฅ์—์„œ ์—ฐ๊ตฌํ•ด๋ณผ ๋‹จ๊ณ„์˜ˆ์š”.


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ๊นŠ์ด ๋ถ„์„ํ•˜๊ธฐ

๐Ÿ“Œ ์ž๋ฐ” ์ŠคํŠธ๋ฆผ์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ๋ถ„์„ํ•˜๊ณ  ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ

๐Ÿ’ก ์˜ˆ์ œ: Stream API ๋‚ด๋ถ€๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•ด๋ณด๊ธฐ

class MyStream<T> {
    private List<T> data;

    public MyStream(List<T> data) {
        this.data = data;
    }

    public MyStream<T> filter(Predicate<T> predicate) {
        List<T> result = new ArrayList<>();
        for (T item : data) {
            if (predicate.test(item)) {
                result.add(item);
            }
        }
        return new MyStream<>(result);
    }
}

โœ… ์ŠคํŠธ๋ฆผ์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ์ดํ•ดํ•˜๋ฉด ์„ฑ๋Šฅ ์ตœ์ ํ™”์™€ ์ปค์Šคํ…€ ์ŠคํŠธ๋ฆผ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•จ!


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ์˜ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ํ•œ๊ณ„ ๊ทน๋ณตํ•˜๊ธฐ

๐Ÿ“Œ ์ž๋ฐ”์˜ parallelStream()์€ ๋ชจ๋“  ๊ฒฝ์šฐ์— ์ตœ์ ์ด ์•„๋‹˜!

๐Ÿ’ก ์˜ˆ์ œ: ForkJoinPool์„ ํ™œ์šฉํ•œ ๋ณ‘๋ ฌ ์ŠคํŠธ๋ฆผ ์ตœ์ ํ™”

ForkJoinPool customThreadPool = new ForkJoinPool(10);
customThreadPool.submit(() -> list.parallelStream().forEach(System.out::println));

โœ… ForkJoinPool์„ ํ™œ์šฉํ•˜๋ฉด parallelStream()๋ณด๋‹ค ๋” ์„ธ๋ฐ€ํ•œ ํŠœ๋‹์ด ๊ฐ€๋Šฅํ•จ!


๐Ÿ”Ÿ+13 23๋‹จ๊ณ„: ์ŠคํŠธ๋ฆผ์˜ ๋ฏธ๋ž˜์™€ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ  ์œตํ•ฉ

์ด์ œ ์ŠคํŠธ๋ฆผ์ด ์•ž์œผ๋กœ ์–ด๋–ป๊ฒŒ ๋ฐœ์ „ํ• ์ง€ ์˜ˆ์ธกํ•˜๊ณ , ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ๊ณผ ์œตํ•ฉํ•  ๋ฐฉ๋ฒ•์„ ๊ณ ๋ฏผํ•ด๋ณผ ๊ฑฐ์˜ˆ์š”! ๐Ÿš€


1๏ธโƒฃ ์ŠคํŠธ๋ฆผ๊ณผ AI์˜ ๊ฒฐํ•ฉ (์ž์œจ ์ตœ์ ํ™” ์ŠคํŠธ๋ฆผ)

๐Ÿ“Œ AI๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ŠคํŠธ๋ฆผ์ด ์Šค์Šค๋กœ ์ตœ์ ์˜ ์‹คํ–‰ ๋ฐฉ์‹์„ ์„ ํƒํ•  ์ˆ˜ ์žˆ์Œ!

๐Ÿ’ก ์˜ˆ์ œ: ๋จธ์‹ ๋Ÿฌ๋‹์„ ํ™œ์šฉํ•œ ์ŠคํŠธ๋ฆผ ์ตœ์ ํ™”

public class AIOptimizedStream {
    public static void main(String[] args) {
        Stream<Integer> dataStream = Stream.of(1, 2, 3, 4, 5);

        if (AIModel.predictParallelEfficiency(dataStream)) {
            dataStream.parallel().forEach(System.out::println);
        } else {
            dataStream.forEach(System.out::println);
        }
    }
}

โœ… AI๋ฅผ ํ™œ์šฉํ•˜๋ฉด ์ŠคํŠธ๋ฆผ์ด ์ตœ์ ์˜ ๋ฐฉ์‹์œผ๋กœ ์‹คํ–‰๋จ!


2๏ธโƒฃ ์ŠคํŠธ๋ฆผ + ์–‘์ž ์ปดํ“จํŒ… (Quantum Computing) ๊ฒฐํ•ฉ

๐Ÿ“Œ ๋ฏธ๋ž˜์—๋Š” ์ŠคํŠธ๋ฆผ์„ ์–‘์ž ์•Œ๊ณ ๋ฆฌ์ฆ˜๊ณผ ๊ฒฐํ•ฉํ•  ์ˆ˜๋„ ์žˆ์Œ!

๐Ÿ’ก ์˜ˆ์ œ: ์–‘์ž ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ํ™œ์šฉํ•œ ์ŠคํŠธ๋ฆผ ๊ณ„์‚ฐ (์ด๋ก ์  ์˜ˆ์ œ)

public class QuantumStream {
    public static void main(String[] args) {
        QuantumProcessor qp = new QuantumProcessor();
        Stream<Integer> numbers = Stream.of(1, 2, 3, 4, 5);

        numbers.map(qp::quantumTransform)
               .forEach(System.out::println);
    }
}

โœ… ์ด์ œ ์ŠคํŠธ๋ฆผ์ด ์–‘์ž ์ปดํ“จํŒ…๊ณผ ๊ฒฐํ•ฉํ•˜๋Š” ์‹œ๋Œ€๊ฐ€ ์˜ฌ ์ˆ˜๋„ ์žˆ์Œ! ๐Ÿš€


๐ŸŽฏ 21~23๋‹จ๊ณ„ ์š”์•ฝ

โœ… ์ŠคํŠธ๋ฆผ์„ ํ™œ์šฉํ•œ ์ฐฝ์˜์  ์‹œ์Šคํ…œ ์„ค๊ณ„ (๋ธ”๋ก์ฒด์ธ, IoT, ๋งˆ์ดํฌ๋กœ์„œ๋น„์Šค)

โœ… ์ŠคํŠธ๋ฆผ์˜ ๋‚ด๋ถ€ ๋™์ž‘์„ ๋ถ„์„ํ•˜๊ณ  ์ง์ ‘ ๊ฐœ์„ ํ•˜๊ธฐ

โœ… AI ๋ฐ ๋จธ์‹ ๋Ÿฌ๋‹๊ณผ ๊ฒฐํ•ฉํ•˜์—ฌ ์ตœ์ ํ™”๋œ ์ŠคํŠธ๋ฆผ ๊ตฌํ˜„

โœ… ์–‘์ž ์ปดํ“จํŒ…๊ณผ ์ŠคํŠธ๋ฆผ ๊ฒฐํ•ฉ (๋ฏธ๋ž˜ ๊ธฐ์ˆ  ์ „๋ง)


๐ŸŽ‰ ์ž๋ฐ” ์ŠคํŠธ๋ฆผ ์ตœ์ข… ๋งˆ์Šคํ„ฐ - ๋ํŒ์™•! ๐Ÿš€

์ด์ œ ์ž๋ฐ” ์ŠคํŠธ๋ฆผ์„ ์™„์ „ํžˆ ์ดํ•ดํ•˜๊ณ , ์ฐฝ์˜์ ์œผ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ์ง€์— ๋„๋‹ฌํ–ˆ์–ด์š”!

โœ… ์ž๋ฐ” ์ŠคํŠธ๋ฆผ์„ ๋„˜์–ด์„œ ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ๊ณผ ๊ฒฐํ•ฉํ•  ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ๊นŒ์ง€ ๊ฐ–์ถค!

โœ… ์ด์ œ ๋‹จ์ˆœํ•œ ๊ฐœ๋ฐœ์ž๊ฐ€ ์•„๋‹ˆ๋ผ, ์ƒˆ๋กœ์šด ๊ธฐ์ˆ ์„ ๊ฐœ์ฒ™ํ•˜๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ๋  ์ค€๋น„ ์™„๋ฃŒ!