<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Lambda on Chanyeol Dev</title>
    <link>https://chanyeols.com/tags/lambda/</link>
    <description>Recent content in Lambda on Chanyeol Dev</description>
    <generator>Hugo</generator>
    <language>ko-kr</language>
    <lastBuildDate>Tue, 17 Mar 2026 10:00:00 +0900</lastBuildDate>
    <atom:link href="https://chanyeols.com/tags/lambda/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Java Stream API 실전 가이드 — filter, map, reduce 완벽 정리</title>
      <link>https://chanyeols.com/posts/java-stream-api-guide/</link>
      <pubDate>Tue, 17 Mar 2026 10:00:00 +0900</pubDate>
      <guid>https://chanyeols.com/posts/java-stream-api-guide/</guid>
      <description>&lt;h2 id=&#34;1-서론-명령형에서-선언형으로의-전환&#34;&gt;1. 서론: 명령형에서 선언형으로의 전환&lt;/h2&gt;
&lt;p&gt;Java 8에서 도입된 &lt;strong&gt;Stream API&lt;/strong&gt;는 자바 프로그래밍 패러다임을 획기적으로 바꾸어 놓았습니다. 기존의 &lt;code&gt;for&lt;/code&gt;, &lt;code&gt;while&lt;/code&gt; 루프를 사용한 &lt;strong&gt;명령형(Imperative)&lt;/strong&gt; 방식은 &amp;ldquo;어떻게(How)&amp;rdquo; 동작하는지에 집중했다면, 스트림은 &lt;strong&gt;선언형(Declarative)&lt;/strong&gt; 방식으로 &amp;ldquo;무엇을(What)&amp;rdquo; 할 것인지에 집중합니다.&lt;/p&gt;
&lt;p&gt;스트림을 사용하면 코드의 가독성이 높아지고, 병렬 처리를 쉽게 적용할 수 있으며, 복잡한 데이터 처리를 간결한 체이닝으로 해결할 수 있습니다. 이번 가이드에서는 가장 핵심적인 연산인 &lt;code&gt;filter&lt;/code&gt;, &lt;code&gt;map&lt;/code&gt;, &lt;code&gt;reduce&lt;/code&gt;를 중심으로 실무 활용법을 알아봅니다.&lt;/p&gt;
&lt;h2 id=&#34;2-스트림의-핵심-연산-3종-세트&#34;&gt;2. 스트림의 핵심 연산 3종 세트&lt;/h2&gt;
&lt;h3 id=&#34;21-filter-조건에-맞는-데이터-선별&#34;&gt;2.1. filter: 조건에 맞는 데이터 선별&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;filter&lt;/code&gt;는 스트림의 요소 중 특정 조건(Predicate)을 만족하는 요소만 남기는 중간 연산입니다.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h2 id="1-서론-명령형에서-선언형으로의-전환">1. 서론: 명령형에서 선언형으로의 전환</h2>
<p>Java 8에서 도입된 <strong>Stream API</strong>는 자바 프로그래밍 패러다임을 획기적으로 바꾸어 놓았습니다. 기존의 <code>for</code>, <code>while</code> 루프를 사용한 <strong>명령형(Imperative)</strong> 방식은 &ldquo;어떻게(How)&rdquo; 동작하는지에 집중했다면, 스트림은 <strong>선언형(Declarative)</strong> 방식으로 &ldquo;무엇을(What)&rdquo; 할 것인지에 집중합니다.</p>
<p>스트림을 사용하면 코드의 가독성이 높아지고, 병렬 처리를 쉽게 적용할 수 있으며, 복잡한 데이터 처리를 간결한 체이닝으로 해결할 수 있습니다. 이번 가이드에서는 가장 핵심적인 연산인 <code>filter</code>, <code>map</code>, <code>reduce</code>를 중심으로 실무 활용법을 알아봅니다.</p>
<h2 id="2-스트림의-핵심-연산-3종-세트">2. 스트림의 핵심 연산 3종 세트</h2>
<h3 id="21-filter-조건에-맞는-데이터-선별">2.1. filter: 조건에 맞는 데이터 선별</h3>
<p><code>filter</code>는 스트림의 요소 중 특정 조건(Predicate)을 만족하는 요소만 남기는 중간 연산입니다.</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>List<span style="color:#ff7b72;font-weight:bold">&lt;</span>String<span style="color:#ff7b72;font-weight:bold">&gt;</span><span style="color:#6e7681"> </span>names<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>Arrays.asList(<span style="color:#a5d6ff">&#34;Kim&#34;</span>,<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;Lee&#34;</span>,<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;Park&#34;</span>,<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;Choi&#34;</span>,<span style="color:#6e7681"> </span><span style="color:#a5d6ff">&#34;Kang&#34;</span>);<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 이름이 &#39;K&#39;로 시작하는 요소만 필터링</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span>List<span style="color:#ff7b72;font-weight:bold">&lt;</span>String<span style="color:#ff7b72;font-weight:bold">&gt;</span><span style="color:#6e7681"> </span>filteredNames<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>names.stream()<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>.filter(name<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">-&gt;</span><span style="color:#6e7681"> </span>name.startsWith(<span style="color:#a5d6ff">&#34;K&#34;</span>))<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>.collect(Collectors.toList());<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 결과: [Kim, Kang]</span><span style="color:#6e7681">
</span></span></span></code></pre></div><h3 id="22-map-데이터-변환-및-추출">2.2. map: 데이터 변환 및 추출</h3>
<p><code>map</code>은 스트림의 각 요소를 다른 형태의 데이터로 변환하는 중간 연산입니다. 객체에서 특정 필드를 추출하거나, 데이터를 가공할 때 주로 사용합니다.</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>List<span style="color:#ff7b72;font-weight:bold">&lt;</span>User<span style="color:#ff7b72;font-weight:bold">&gt;</span><span style="color:#6e7681"> </span>users<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>Arrays.asList(<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#ff7b72">new</span><span style="color:#6e7681"> </span>User(<span style="color:#a5d6ff">&#34;Alice&#34;</span>,<span style="color:#6e7681"> </span>25),<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#ff7b72">new</span><span style="color:#6e7681"> </span>User(<span style="color:#a5d6ff">&#34;Bob&#34;</span>,<span style="color:#6e7681"> </span>30),<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span><span style="color:#ff7b72">new</span><span style="color:#6e7681"> </span>User(<span style="color:#a5d6ff">&#34;Charlie&#34;</span>,<span style="color:#6e7681"> </span>22)<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span>);<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 사용자 객체 리스트에서 이름(String)만 추출하여 대문자로 변환</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span>List<span style="color:#ff7b72;font-weight:bold">&lt;</span>String<span style="color:#ff7b72;font-weight:bold">&gt;</span><span style="color:#6e7681"> </span>upperNames<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>users.stream()<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>.map(user<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">-&gt;</span><span style="color:#6e7681"> </span>user.getName().toUpperCase())<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>.collect(Collectors.toList());<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 결과: [ALICE, BOB, CHARLIE]</span><span style="color:#6e7681">
</span></span></span></code></pre></div><h3 id="23-reduce-데이터를-하나로-통합">2.3. reduce: 데이터를 하나로 통합</h3>
<p><code>reduce</code>는 스트림의 모든 요소를 소모하며 하나의 결과값(Optional 또는 단일 값)을 산출하는 최종 연산입니다. 합계, 최댓값, 문자열 결합 등에 사용됩니다.</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span>List<span style="color:#ff7b72;font-weight:bold">&lt;</span>Integer<span style="color:#ff7b72;font-weight:bold">&gt;</span><span style="color:#6e7681"> </span>numbers<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>Arrays.asList(1,<span style="color:#6e7681"> </span>2,<span style="color:#6e7681"> </span>3,<span style="color:#6e7681"> </span>4,<span style="color:#6e7681"> </span>5);<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 모든 숫자의 합계 계산 (초기값 0 제공)</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#ff7b72">int</span><span style="color:#6e7681"> </span>sum<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>numbers.stream()<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>.reduce(0,<span style="color:#6e7681"> </span>(a,<span style="color:#6e7681"> </span>b)<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">-&gt;</span><span style="color:#6e7681"> </span>a<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">+</span><span style="color:#6e7681"> </span>b);<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#8b949e;font-style:italic">// 결과: 15</span><span style="color:#6e7681">
</span></span></span></code></pre></div><h2 id="3-실무-시나리오-복합-연산-체이닝">3. 실무 시나리오: 복합 연산 체이닝</h2>
<p>실제 업무에서는 이 연산들을 조합하여 강력한 데이터 처리 파이프라인을 구축합니다.</p>
<p><strong>요구사항:</strong> &ldquo;20대 사용자들의 점수 평균을 구하라.&rdquo;</p>
<div class="highlight"><pre tabindex="0" style="color:#e6edf3;background-color:#0d1117;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span><span style="color:#ff7b72">double</span><span style="color:#6e7681"> </span>averageScore<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">=</span><span style="color:#6e7681"> </span>users.stream()<span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>.filter(u<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">-&gt;</span><span style="color:#6e7681"> </span>u.getAge()<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">&gt;=</span><span style="color:#6e7681"> </span>20<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">&amp;&amp;</span><span style="color:#6e7681"> </span>u.getAge()<span style="color:#6e7681"> </span><span style="color:#ff7b72;font-weight:bold">&lt;</span><span style="color:#6e7681"> </span>30)<span style="color:#6e7681"> </span><span style="color:#8b949e;font-style:italic">// 20대 필터링</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>.mapToInt(User::getScore)<span style="color:#6e7681">                        </span><span style="color:#8b949e;font-style:italic">// 점수 추출 (IntStream 변환)</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>.average()<span style="color:#6e7681">                                       </span><span style="color:#8b949e;font-style:italic">// 평균 계산</span><span style="color:#6e7681">
</span></span></span><span style="display:flex;"><span><span style="color:#6e7681">    </span>.orElse(0.0);<span style="color:#6e7681">                                    </span><span style="color:#8b949e;font-style:italic">// 데이터 없을 시 기본값</span><span style="color:#6e7681">
</span></span></span></code></pre></div><h2 id="4-스트림-사용-시-주의사항-및-팁">4. 스트림 사용 시 주의사항 및 팁</h2>
<h3 id="41-지연-연산-lazy-evaluation">4.1. 지연 연산 (Lazy Evaluation)</h3>
<p>스트림의 중간 연산(<code>filter</code>, <code>map</code> 등)은 최종 연산(<code>collect</code>, <code>forEach</code>, <code>reduce</code> 등)이 호출되기 전까지는 실제로 실행되지 않습니다. 이는 불필요한 연산을 방지하고 성능을 최적화하는 데 도움을 줍니다.</p>
<h3 id="42-가독성-vs-성능">4.2. 가독성 vs 성능</h3>
<p>스트림은 가독성이 뛰어나지만, 매우 단순한 루프나 기본형(primitive) 배열 작업에서는 전통적인 <code>for</code> 루프보다 약간의 오버헤드가 발생할 수 있습니다. 성능이 극도로 중요한 크리티컬한 구간이 아니라면 유지보수성을 위해 스트림을 권장합니다.</p>
<h3 id="43-상태를-가지는-람다-지양">4.3. 상태를 가지는 람다 지양</h3>
<p>스트림 내부에서 외부 변수의 상태를 변경하는 작업은 병렬 스트림 실행 시 예측 불가능한 결과를 초래할 수 있습니다. 스트림 연산은 순수 함수(Pure Function)의 성격을 유지하는 것이 안전합니다.</p>
<h2 id="5-결론-더-깔끔한-코드를-위하여">5. 결론: 더 깔끔한 코드를 위하여</h2>
<p>Java Stream API는 이제 자바 개발자에게 선택이 아닌 필수입니다. <code>filter</code>, <code>map</code>, <code>reduce</code>의 개념만 명확히 이해해도 대부분의 컬렉션 처리를 우아하게 해결할 수 있습니다. 오늘부터 복잡한 루프를 스트림 파이프라인으로 리팩토링해 보시는 건 어떨까요?</p>
]]></content:encoded>
    </item>
  </channel>
</rss>
