** ๐1๋จ๊ณ: ์คํธ๋ฆผ(Stream)์ด๋? ์ฝ๊ฒ ์ดํดํ๊ธฐ**
๐ฏ ๊ฐ๋ฌผ๊ณผ ๊ฐ์ ๋ฐ์ดํฐ ํ๋ฆ!
์คํธ๋ฆผ์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ๋ฌผ์ฒ๋ผ ํ๋ฅด๊ฒ ํ๋ฉด์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ์ด์์.
๐ง ๋น์ :
- ์์ ๋ฐฉ์(์๋์ด ๋ฐฉ์): ๋ฐ์ดํฐ๋ฅผ ํ๋์ฉ ๊บผ๋ด์ ๊ฐ๊ณตํด์ผ ํจ. (for๋ฌธ ์ฌ์ฉ)
- ์คํธ๋ฆผ ๋ฐฉ์(๊ฐ๋ฌผ ๋ฐฉ์): ๋ฐ์ดํฐ๋ฅผ ํ๋ ค๋ณด๋ด๋ฉด์ ํ์ํ ๊ฒ๋ง ๊ฑธ๋ฌ์ ์ฌ์ฉ!
๐ก ์คํธ๋ฆผ์ ํน์ง
โ ๋ฐ์ดํฐ๋ฅผ ์ง์ ์ ์ฅํ์ง ์๊ณ , โํ๋ฆโ๋ง ๋ค๋ฃฌ๋ค.
โ ์ค๊ฐ ์ฐ์ฐ(ํํฐ๋ง, ๋ณํ)์ ์ค์ ์คํ๋์ง ์๋ค๊ฐ, ์ต์ข ์ฐ์ฐ(์ถ๋ ฅ, ํฉ๊ณ ๋ฑ)์ ๋ง๋์ผ ์คํ๋จ.
โ ๋ณ๋ ฌ ์ฒ๋ฆฌ(์ฌ๋ฌ ๊ฐ์ 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)๊ณผ ์ฑ๋ฅ ์ต์ ํ
๐ ๋ณ๋ ฌ ์คํธ๋ฆผ์ด๋?
- ์ฌ๋ฌ ๊ฐ์ CPU๋ฅผ ํ์ฉํด์ ๋ฐ์ดํฐ๋ฅผ ๋์์ ์ฒ๋ฆฌํ๋ ๋ฐฉ๋ฒ!
parallelStream()
์ ์ฌ์ฉํ๋ฉด ์๋์ผ๋ก ๋ณ๋ ฌ ์คํ๋จ.
๐ ๋ณ๋ ฌ ์คํธ๋ฆผ ์์ (๋ณ๋ ฌ ์คํ ํ์ธํ๊ธฐ)
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
โ ์ฌ๋ฌ ์ค๋ ๋์์ ๋์์ ์คํ๋จ!
๐จ ์ฃผ์:
- ๋ฐ์ดํฐ ํฌ๊ธฐ๊ฐ ์์ผ๋ฉด ๋ณ๋ ฌ ์คํธ๋ฆผ์ด ๋ ๋๋ ค์ง ์ ์์!
- ์์๊ฐ ์ค์ํ ๊ฒฝ์ฐ
forEachOrdered()
์ฌ์ฉํด์ผ ํจ.
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๋จ๊ณ: ์คํธ๋ฆผ ์ฑ๋ฅ ์ต์ ํ & ์ค์ ํ
๐ ์ต์ ํ ํต์ฌ ํฌ์ธํธ!
โ ๋ถํ์ํ ์ฐ์ฐ ์ค์ด๊ธฐ
filter()
โmap()
์์๋ก ์คํ!limit()
์sorted()
๋ณด๋ค ๋จผ์ ์คํ!
โ ๋ณ๋ ฌ ์คํธ๋ฆผ ํ์ฉ (๋์ฉ๋ ๋ฐ์ดํฐ์ ํ์ !)
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)๋ฅผ ์ ์งํด์ผ ํ๋ ๊ฒฝ์ฐ
- ์คํธ๋ฆผ์ ๋ถ๋ณ์ฑ(Immutability) ์ ์ ์งํ๊ธฐ ๋๋ฌธ์, ๋ด๋ถ ์ํ๋ฅผ ๋ณ๊ฒฝํ๋ ์์ ์ด ์ด๋ ค์์.
- ์:
count++
๊ฐ์ ์ํ ๋ณ๊ฒฝ์ด ํ์ํ ๊ฒฝ์ฐ for๋ฌธ์ด ๋ ์ ์ ํ ์ ์์ด์.
2๏ธโฃ ์์ธ(Exception) ์ฒ๋ฆฌ ์ด๋ ค์
- ์คํธ๋ฆผ ๋ด๋ถ์์
try-catch
๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฐ๋ ์ฑ์ด ๋จ์ด์ง. - ํด๊ฒฐ ๋ฐฉ๋ฒ:
.map(this::safeMethod)
๊ฐ์ ๋ฐฉ์ ์ฌ์ฉ.
3๏ธโฃ ๋๋ฒ๊น ์ด ์ด๋ ค์
- ์คํธ๋ฆผ์ ํ ์ค๋ก ํํ๋๋ ๊ฒฝ์ฐ๊ฐ ๋ง์ ์ค๊ฐ ๊ณผ์ ๋๋ฒ๊น ์ด ์ด๋ ต๋ค!
- ํด๊ฒฐ ๋ฐฉ๋ฒ:
peek()
ํ์ฉ!
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");
}
}
โ ๊ฒฐ๊ณผ:
- CPU ์ฝ์ด๊ฐ ๋ง์์๋ก ๋ณ๋ ฌ ์คํธ๋ฆผ์ด ๋ ๋น ๋ฆ!
- ํ์ง๋ง ๋ฐ์ดํฐ๊ฐ ์ ๊ฑฐ๋ ๋จ์ ์ฐ์ฐ์ด๋ฉด ์คํ๋ ค ๋ณ๋ ฌ ์คํธ๋ฆผ์ด ๋๋ฆด ์๋ ์์!
๐ ๋ณ๋ ฌ ์คํธ๋ฆผ ์ฌ์ฉ์ด ์ ๋ฆฌํ ๊ฒฝ์ฐ
โ ๋ฐ์ดํฐ ํฌ๊ธฐ๊ฐ ํฌ๊ณ , ์ฐ์ฐ์ด ๋ณต์กํ ๋
โ 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 (๊ฐ์ ์ค๋ ๋) ๋์
parallelStream()
๋ณด๋ค ๊ฐ๋ฒผ์ด ์ค๋ ๋๋ฅผ ํ์ฉํ๋ ๋ฐฉ์์ด ๋์ธ๊ฐ ๋ ์์ !Executors.newVirtualThreadPerTaskExecutor()
๋ฅผ ํ์ฉํ๋ฉด ๋ณ๋ ฌ ์ฒ๋ฆฌ๋ฅผ ๋ ์ฝ๊ฒ ๊ตฌํ ๊ฐ๋ฅ.
โ Structured Concurrency ๋์
- ์คํธ๋ฆผ์ ๋์ฒดํ ์๋ก์ด ๋ณ๋ ฌ ํ๋ก๊ทธ๋๋ฐ ํจํด ๋ฑ์ฅ!
- ๊ธฐ์กด
parallelStream()
๋ณด๋ค ๋ ์์ ์ ์ธ ๋ฐฉ์.
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)
- ์คํธ๋ฆผ์ ํ์ฉํ๋ฉด ์ด๋ฒคํธ ๊ธฐ๋ฐ ์์คํ ์์ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์.
- Kafka + Stream API๋ฅผ ์ฌ์ฉํ๋ฉด ๋ง์ดํฌ๋ก์๋น์ค ๊ฐ ๋น๋๊ธฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ๊ฐ ๊ฐ๋ฅ!
2๏ธโฃ ๋ฐ์ดํฐ ํ์ดํ๋ผ์ธ ๊ตฌ์ถ (Data Pipeline)
- ์คํธ๋ฆผ์ ํ์ฉํ๋ฉด ๋๊ท๋ชจ ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ๋ณํ, ํํฐ๋ง, ์ ์ฅํ ์ ์์.
- Apache Kafka, Spark Streaming ๊ฐ์ ๊ธฐ์ ๊ณผ ๊ฒฐํฉ ๊ฐ๋ฅ!
๐ก ์์ : 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๏ธโฃ ์คํธ๋ฆผ ๊ธฐ๋ฐ์ ๋ถ์ฐ ์์คํ ์ค๊ณ
์คํธ๋ฆผ์ ํ์ฉํ๋ฉด ๋ถ์ฐ ์์คํ ์ ๋ ํจ์จ์ ์ผ๋ก ์ค๊ณํ ์ ์์ด์.
๐ ์์ : ์ค์๊ฐ ๊ธ์ต ๋ฐ์ดํฐ ๋ถ์ ์์คํ
- Kafka๋ฅผ ์ด์ฉํด ๊ธ์ต ๋ฐ์ดํฐ๋ฅผ ์คํธ๋ฆผ์ผ๋ก ์์ง
- Spark Streaming์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ณํ & ๋ถ์
- Spring WebFlux๋ฅผ ์ฌ์ฉํด ๋น๋๊ธฐ ์๋ต ์ฒ๋ฆฌ
๐ก ์์ : ๋ถ์ฐ ํ๊ฒฝ์์ ์ค์๊ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌํ๋ ๊ตฌ์กฐ
KStream<String, Transaction> transactions = builder.stream("transactions");
transactions.filter((key, tx) -> tx.getAmount() > 10000)
.to("high-value-transactions");
โ ์ด๋ฐ ์์คํ ์ ํ์ฉํ๋ฉด, ์ค์๊ฐ์ผ๋ก ๊ธ์ต ์ฌ๊ธฐ๋ฅผ ํ์งํ ์๋ ์์!
2๏ธโฃ ์คํธ๋ฆผ + ๋ธ๋ก์ฒด์ธ ๊ธฐ์ ๊ฒฐํฉ
๐ ์คํธ๋ฆผ์ ํ์ฉํ๋ฉด ๋ธ๋ก์ฒด์ธ์ ํธ๋์ญ์ ์ ์ค์๊ฐ์ผ๋ก ๋ถ์ํ ์ ์์ด์!
- Bitcoin, Ethereum ๋ธ๋ก์ฒด์ธ์ ์ค์๊ฐ ๋ฐ์ดํฐ ๋ถ์
- ๋ถ์ฐ ์์ฅ์ ํจ์จ์ ์ผ๋ก ์ฟผ๋ฆฌํ๋ ์คํธ๋ฆผ ๊ธฐ๋ฐ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์์คํ ๊ตฌ์ถ
๐ก ์์ : ๋ธ๋ก์ฒด์ธ ํธ๋์ญ์ ์คํธ๋ฆผ ๋ถ์
transactions.stream()
.filter(tx -> tx.getValue() > 1.0) // 1 BTC ์ด์ ๊ฑฐ๋ ํํฐ๋ง
.forEach(tx -> System.out.println("High-value transaction: " + tx));
โ ๋ธ๋ก์ฒด์ธ ๊ธฐ์ ๊ณผ ์คํธ๋ฆผ์ ๊ฒฐํฉํ๋ฉด ์๋ก์ด ๊ฐ๋ฅ์ฑ์ด ์ด๋ฆผ!
3๏ธโฃ ์คํธ๋ฆผ ๊ธฐ๋ฐ IoT ๋ฐ์ดํฐ ์ฒ๋ฆฌ
๐ IoT ์ผ์ ๋ฐ์ดํฐ๋ฅผ ์คํธ๋ฆผ์ผ๋ก ๋ถ์ํ๋ฉด ์ค์๊ฐ ๋ชจ๋ํฐ๋ง์ด ๊ฐ๋ฅํด์!
- ์ค๋งํธ ๊ณต์ฅ(Smart Factory)์ ์ค์๊ฐ ๋ฐ์ดํฐ ๋ถ์
- ์์จ ์ฃผํ์ฐจ์ ์ผ์ ๋ฐ์ดํฐ ์ค์๊ฐ ๋ถ์
๐ก ์์ : 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()
์ ๋ชจ๋ ๊ฒฝ์ฐ์ ์ต์ ์ด ์๋!
parallelStream()
์ CPU ์ฝ์ด ๊ฐ์์ ๋ฐ๋ผ ์ฑ๋ฅ์ด ๋ฌ๋ผ์ง- ForkJoinPool์ ํ์ฉํ๋ฉด ๋ ์ธ๋ฐํ ๋ณ๋ ฌ ์ฒ๋ฆฌ ๊ฐ๋ฅ
๐ก ์์ : 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 ๋ฐ ๋จธ์ ๋ฌ๋๊ณผ ๊ฒฐํฉํ์ฌ ์ต์ ํ๋ ์คํธ๋ฆผ ๊ตฌํ
โ ์์ ์ปดํจํ ๊ณผ ์คํธ๋ฆผ ๊ฒฐํฉ (๋ฏธ๋ ๊ธฐ์ ์ ๋ง)
๐ ์๋ฐ ์คํธ๋ฆผ ์ต์ข ๋ง์คํฐ - ๋ํ์! ๐
์ด์ ์๋ฐ ์คํธ๋ฆผ์ ์์ ํ ์ดํดํ๊ณ , ์ฐฝ์์ ์ผ๋ก ํ์ฉํ ์ ์๋ ๊ฒฝ์ง์ ๋๋ฌํ์ด์!
โ ์๋ฐ ์คํธ๋ฆผ์ ๋์ด์ ์๋ก์ด ๊ธฐ์ ๊ณผ ๊ฒฐํฉํ ์ ์๋ ๋ฅ๋ ฅ๊น์ง ๊ฐ์ถค!
โ ์ด์ ๋จ์ํ ๊ฐ๋ฐ์๊ฐ ์๋๋ผ, ์๋ก์ด ๊ธฐ์ ์ ๊ฐ์ฒํ๋ ๊ฐ๋ฐ์๊ฐ ๋ ์ค๋น ์๋ฃ!