0. ์ปฌ๋ ์


์ปฌ๋ ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๊ทธ๋ฃนํํ๊ณ ์ฒ๋ฆฌํ๋ ํน์ง์ ์ด๋ ค sql ์ง์์ ๊ฐ์ด ๋น์ทํ๊ฒ ๋ง๋ค ์ ์๋ค.
→ ์ ์ธํ
์ด์ ๊ฐ์ด ๋ง์ ์์๋ฅผ ํฌํจํ๋ ์ปค๋ค๋ ์ปฌ๋ ์ ์ ๋ณ๋ ฌ ์ฒ๋ฆฌ ์ฝ๋๊ฐ ํ์ํ๋ค.
⇒ ์คํธ๋ฆผ์ด ํด๊ฒฐ์ฑ !
1. ์คํธ๋ฆผ ์๊ฐ
- ์๋ฐ 8์์ ์ถ๊ฐ๋ ๊ธฐ๋ฅ
- ์ ์ธํ์ผ๋ก ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ฐ๋ฅ
- ๋ฉํฐ์ค๋ ๋ ์ฝ๋ ๊ตฌํ ์์ด ๋ณ๋ ฌ๋ก ํฌ๋ช
ํ๊ฒ ์ฒ๋ฆฌ ๊ฐ๋ฅ
- ๋ฐ์ดํฐ ์ฒ๋ฆฌ ๊ณผ์ ์ ๋ณ๋ ฌํํ๋ฉด์ ์ค๋ ๋์ ๋ฝ์ ๊ฑฑ์ ํ ํ์๊ฐ ์์
- ์คํธ๋ฆผ ์ ์ฉ ์ ์ ์๋ฐ 7์ฝ๋
List<Dish> lowCaloricDishes = new ArrayList<>(); for(Dish dish: menu) { // ๋์ ์๋ก ์์ ํํฐ๋ง if(dish.getCalories() < 400) { lowCaloricDishes.add(dish); } } // ์ต๋ช ํด๋์ค๋ก ์๋ฆฌ ์ ๋ ฌ Collections.sort(lowCaloricDishes, new Comparator<Dish>() { public int compare(Dish dish1, Dish dish2) { return Integer.compare(dish.getCalories(), dish2.getCalories()); } }); List<String> lowCaloricDishesName = new ArrayList<>(); for(Dish dish: lowCaloricDishes) { // ์ ๋ ฌ๋ ๋ฆฌ์คํธ๋ฅผ ์ฒ๋ฆฌํ๋ฉด์ ์๋ฆฌ ์ด๋ฆ ์ ํ lowCaloricDishesName.add(dish.getName()); }
- lowCaloricDishes → ๊ฐ๋น์ง ๋ณ์ ์ฌ์ฉ
- ์คํธ๋ฆผ ์ ์ฉ ํ์ ์๋ฐ 8 ์ฝ๋
List<String> lowCaloricDishesName = menu.stream() .filter(d -> d.getCalories() < 400) .sorted(comparing(Dish::getCalories)) .map(Dish::getName) .collect(toList()); // stream -> parallelStream()์ ์ด์ฉํ์ฌ ๋ฉํฐ์ฝ์ด ์ํคํ ์ฒ์์ ๋ณ๋ ฌ๋ก ์คํ List<String> lowCaloricDishesName = menu.parallelStream() .filter(d -> d.getCalories() < 400) .sorted(comparing(Dish::getCalories)) .map(Dish::getName) .collect(toList());
๋ฑ ๋ด๋ ์ฝ๋์๋ถํฐ ์ฐจ์ด๊ฐ ๋๋ค.
์คํธ๋ฆผ์ ํน์ง
1. ์ ์ธํ : ๋ ๊ฐ๊ฒฐํ๊ณ ๊ฐ๋ ์ฑ์ด ์ข์์ง๋ค.

⇒ ๊ธฐ์กด์๋ ์๊ตฌ์ฌํญ์ด ๋ณ๊ฒฝ๋๋ฉด ๊ธฐ์กด ์ฝ๋๋ฅผ ๋ณต์ฌ ๋ถ์ฌ๋ฃ๊ธฐ๋ฅผ ํด์ผํ์ง๋ง, ๋๋คํํ์์ผ๋ก ํํฐ๋งํ๋ ์ฝ๋๋ฅผ ๋ณ๊ฒฝํ๊ธฐ๋ง ํ๋ฉด ๊ฐ๋จํ๊ฒ ์๊ตฌ์ฌํญ์ ๋ง์ถ ์๊ฐ ์๊ฒ ๋์๋ค.
2. ์กฐ๋ฆฝํ ์ ์์ : ์ ์ฐ์ฑ์ด ์ข์์ง๋ค.
3. ๋ณ๋ ฌํ : ์ฑ๋ฅ์ด ์ข์์ง๋ค.

๊ฐ๊ฐ์ filter, sorted, map ๊ณผ ๊ฐ์ “๋น๋ฉ ๋ธ๋ก” ์ฐ์ฐ ์ ์ฐ๊ฒฐํด์ ๋ณต์กํ ๋ฐ์ดํฐ ์ฒ๋ฆฌ ํ์ดํ ๋ผ์ธ์ ๋ง๋ค ์๊ฐ ์๋ค.
์์ด๋ก building block์ ๋ฒฝ๋ ํน์ ์ง ์ง๋ ๋ธ๋ก์ ๋ปํ๋๋ฐ, building blocks์ฒ๋ผ ๋ณต์๋ก ์ฐ์ด๋ฉด “๊ธฐ๋ณธ (๊ตฌ์ฑ)์์”๋ผ๋ ๋ป์ด ์๋ค.
์ด๋ ๊ฒ ์๊ฐํ๋ฉด ๋ฝ ์ดํด๊ฐ ๋๋ค.
์๋ฐ์ ๊ธฐ๋ณธ ๊ตฌ์ฑ์์๊ฐ ๋ฌด์์ธ๊ฐ? ํด๋์ค์ ๋ฉ์๋ ๊ทธ๋ฆฌ๊ณ ์ฌ๋ฌ ํ๋๋ฑ ์ผ ๊ฒ์ด๋ค. ๋ฐ๋ผ์ ์ฌ๊ธฐ์ ๋น๋ฉ ๋ธ๋ก์ ์๋ฐ์ ํด๋์ค ๋จ์๋ฅผ ๋งํ๋ค.
์ฑ ์์๋ filter์ ๊ฐ์ ์ฐ์ฐ๋ค์(sorted, map, collect) ๊ณ ์์ค ๋น๋ฉ ๋ธ๋ก์ผ๋ก ์ด๋ฃจ์ด์ ธ ์๋ค๊ณ ํ๋ค.
๋ฐ๊ฟ์ ๋งํ์๋ฉด, ๊ณ ์์ค ๊ตฌ์ฑ์์๋ผ ํ ์ ์๊ฒ ๋ค.

๊ณ ์์ค ๊ตฌ์ฑ ์์์ฏค์ ์ด๋ฏธ ์๊ณ ์๋ ๊ฐ๋ ์ด๋ค.
๊ฐ์ฒด ์งํฅ์์ ์ธํฐํ์ด์ค์ ์์กดํด์ผ ์บก์ํ๊ฐ ๊นจ์ง์ง ์์์ ๋ฐฐ์ฐ๊ณ ์๋ค. ์ฌ๊ธฐ์ ์ด ์ถ์ํ๋ ์ธํฐํ์ด์ค๊ฐ ๊ณ ์์ค ๊ตฌ์ฑ ์์์ธ ๊ฒ์ด๋ค.
์ ๋ค์ ์ฑ ์ผ๋ก ๋์๊ฐ์ ๋ด์ฉ์ ์ดํด๋ณด๋ฉด, ๊ณ ์์ค ๋น๋ฉ ๋ธ๋ก์ผ๋ก ์ด๋ฃจ์ด์ ธ ์๊ธฐ ๋๋ฌธ์ ํน์ ์ค๋ ๋ฉ ๋ชจ๋ธ์ ์ ํ๋์ง ์๊ณ ์์ ๋กญ๊ฒ ์ด๋ค ์ํฉ์์๋ ์ฌ์ฉํ ์ ์๋ค๊ณ ํ๋ค.
⇒ ๋น์ฐํ๋ค. ์๋จ ์ด๋์ ์์กด์ ์ธ ์ ๋ค์ด ์๋๋๊น ์ ํ๋์ง ์๋ ๊ฒ์ด๋ค.

์ฝ๋๋ฅผ ๊น๋ณด๋ฉด ์ด๋ฏธ Stream ๋ถํฐ๊ฐ ์ธํฐํ์ด์ค์ด๊ณ , ์ธํฐํ์ด์ค ์์ ๋ฉ์๋๋ ์์ฐ์ค๋ฝ๊ฒ ์ถ์ ๋ฉ์๋์ด๋ค.
filter ์์ฒด๋ง ๋ณด๋ฉด ๋ฑํ ๋ญ ๋ฉํฐ ์ฝ์ด ํ๊ฒฝ์ ์ ํฉํ๊ฒ ์ง์ฌ ์๋ ๋ฏํ ๋๋์ ์๋๋ฐ,
๊ทธ๋ฆฌ๊ณ Collection ์ฝ๋๋ฅผ ํ์ธํด๋ณด๋ฉด
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
์ด๋ ๊ฒ ๋ด๋ถ์ ์ผ๋ก StreamSupportํด๋์ค์์ Boolean๊ฐ์ผ๋ก ๊ตฌ๋ณํด์ ๋ฉํฐ์ค๋ ๋์ ๋ง๊ฒ ์ฌ์ฉํ ์ ์๋๋ก ๋์ด์๋ค.
์์ ์ฝ๋
List<Dish> menu = Arrays.asList( new Dish("pork", false, 800, Dish.Type.MEAT), new Dish("beef", false, 700, Dish.Type.MEAT), new Dish("chicken", false, 400, Dish.Type.MEAT), new Dish("french fries", true, 530, Dish.Type.OTHER), new Dish("rice", true, 350, Dish.Type.OTHER), new Dish("season fruit", true, 120, Dish.Type.OTHER), new Dish("pizza", true, 550, Dish.Type.OTHER), new Dish("prawns", false, 400, Dish.Type.FISH), new Dish("salmon", false, 450, Dish.Type.FISH) );
- ๋ถ๋ณํ ์ฝ๋ → Setter ์์
public class Dish { private final String name; private final boolean vegetarian; private final int calories; private final Type type; public Dish(String name, boolean vegetarian, int calories, Type type) { this.name = name; this.vegetarian = vegetarian; this.calories = calories; this.type = type; } public String getName() { return name; } public boolean isVegetarian() { return vegetarian; } public int getCalories() { return calories; } public Type getType() { return type; } public enum Type { MEAT, FISH, OTHER } }
2. ์คํธ๋ฆผ ์์ํ๊ธฐ
์คํธ๋ฆผ์ด๋? : ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ฐ์ฐ์ ์ง์ํ๋๋ก ์์ค์์ ์ถ์ถ๋ ์ฐ์๋ ์์
- ์ฐ์๋ ์์
- ์คํธ๋ฆผ๋ ์ปฌ๋ ์ ์ฒ๋ผ ํน์ ์์ ํ์์ผ๋ก ์ด๋ฃจ์ด์ง ์ฐ์๋ ๊ฐ ์งํฉ์ ์ธํฐํ์ด์ค๋ฅผ ์ ๊ณตํ๋ค.
public static <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel) { Objects.requireNonNull(spliterator); return new ReferencePipeline.Head<>(spliterator, StreamOpFlag.fromCharacteristics(spliterator), parallel); }
- ์์ค
- ์คํธ๋ฆผ์ ์ปฌ๋ ์ , ๋ฐฐ์ด, I/O ์์ ๋ฑ ๋ฐ์ดํฐ ์ ๊ณต ์์ค๋ก๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์๋นํ๋ค.
- ReferencePipeline ์ฝ๋ ์ฐธ๊ณ
๋ณด๋ค์ํผ ์ ๋ ฌ๋๊ฑฐ๋ ์ ๋ ฌ๋ ๊ทธ๋๋ก ์ ์งํด์ ์ฒ๋ฆฌํ๋ค.@Override public void forEach(Consumer<? super E_OUT> action) { if (!isParallel()) { sourceStageSpliterator().forEachRemaining(action); } else { super.forEach(action); } } @Override public void forEachOrdered(Consumer<? super E_OUT> action) { if (!isParallel()) { sourceStageSpliterator().forEachRemaining(action); } else { super.forEachOrdered(action); } }
- ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ฐ์ฐ
- ์คํธ๋ฆผ์ ํจ์ํ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด์์ ์ผ๋ฐ์ ์ผ๋ก ์ง์ํ๋ ์ฐ์ฐ + ๋ฐ์ดํฐ๋ฒ ์ด์ค์ ๋น์ทํ ์ฐ์ฐ ๋ชจ๋ ์ ๊ณตํ๋ค.
- ํ์ดํ๋ผ์ด๋
- ์์ ์คํธ๋ฆผ์ ํน์ง์ ์กฐ๋ฆฝํ ์ ์๋ ์ ์ด ์์๋๋ฐ, ์คํธ๋ฆผ์ ์ฐ์ฐ๋ผ๋ฆฌ ์ฐ๊ฒฐํด์ ์ปค๋ค๋ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ ์ ์๋๋ก ์คํธ๋ฆผ ์์ ์ ๋ฐํํ๋ค.→ ์ด๊ฑด ๊ฒ์ผ๋ฆ(laziness), ์ผํธ ์ํท (short-circuiting)๊ณผ ๊ฐ์ ์ต์ ํ๋ ์ป์ ์ ์๋ค๋๋ฐ, 5์ฅ์์ ์์๋ณด์. ์ง๊ธ์ ๋ชจ๋ฆ
- → ์ฐ์ฐ ํ์ดํ๋ผ์ธ์ ๋ฐ์ดํฐ ์์ค์ ์ ์ฉํ๋ DB์ง์์ ๋น์ทํ๊ฒ ์๊ฒผ๋ค.
- ๋ด๋ถ ๋ฐ๋ณต
- ๋ฐ๋ณต์๋ฅผ ์ด์ฉํด์ ๋ช ์์ ์ผ๋ก ๋ฐ๋ณตํ๋ ์ปฌ๋ ์ ๊ณผ๋ ๋ฌ๋ฆฌ ์คํธ๋ฆผ์ ๋ด๋ถ ๋ฐ๋ณต์ ์ง์ํ๋ค.
์์ ์ดํด๋ณด๊ธฐ

List<String> threeHighCaloricDishNames =
menu.stream() //๋ฉ๋ด(์๋ฆฌ ๋ฆฌ์คํธ)์์ ์คํธ๋ฆผ ์ป๊ธฐ
.filter(dish -> dish.getCalories()> 300) // ํ์ดํ ์ฐ์ฐ ๋ง๋ค๊ธฐ, ์ฒซ ๋ฒ์งธ๋ก ๊ณ ์นผ๋ก๋ฆฌ ์๋ฆฌ๋ฅผ ํํฐ๋ง
.map(Dish::getName) //์๋ฆฌ๋ช
์ถ์ถ
.limit(3) //์ ์ฐฉ์ 3๊ฐ๋ก ์ ํ
.collect(toList()); //๊ฒฐ๊ณผ๋ฅผ ๋ค๋ฅธ ๋ฆฌ์คํธ๋ก ์ ์ฅ
System.out.println(threeHighCaloricDishNames); //[pork, beef, chicken]
- ๋ฐ์ดํฐ ์์ค : ์๋ฆฌ ๋ฆฌ์คํธ(๋ฉ๋ด) → ์ฐ์๋ ์์๋ก์ ์คํธ๋ฆผ์ด ์ ๊ณต๋จ
- ๋ฐ์ดํฐ ์ฒ๋ฆฌ ์ฐ์ฐ : filter, map, limit, collect๋ก ์ด์ด์ง
- collect๋ฅผ ์ ์ธํ ์ฐ์ฐ์ ์๋ก ํ์ดํ๋ผ์ธ ํ์ฑ์ ์ํด ์คํธ๋ฆผ ์์ ์ ๋ฐํ
3. ์คํธ๋ฆผ๊ณผ ์ปฌ๋ ์


ํ๋ง๋๋ก ์คํธ๋ฆผ์ ์ง์ฐ ๋ก๋ฉ์ด๋ค.
๊ทธ๋ฆผ์ฒ๋ผ ์คํธ๋ฆฌ๋ฐ์ ์ฒ๋ฆฌํ ๋ ์ ์ด์ ๋ฐ์ดํฐ ์์ฒด๊ฐ ์ค์๊ฐ์ผ๋ก ์๊ฒจ๋๋ ๊ฑฐ๊ธฐ ๋๋ฌธ์ ๋ฏธ๋ฆฌ ๋ก๋ฉํด์ ์ฒ๋ฆฌํ๋ คํด๋ ๋ญ๊ฐ ์๋ค.
๋ฐ๋๋ก, DVD ํ๋ ์ด์ด๋ ์ ์ฅ๋ ๋น๋์ค๋ฅผ ๋ค ๋ถ๋ฌ์จ ๋ค์์ ์คํ๋๋ค.
์ปฌ๋ ์ ๊ณผ ์คํธ๋ฆผ์ ์ฐจ์ด๋ ์ด๋ฐ ๊ฒ์ด๋ค.
๋ฑ ํ๋ฒ๋ง ํ์๊ฐ๋ฅํ๋ค.
๋ฐ๋ณต์์ ๋ง์ฐฌ๊ฐ์ง๋ก ํ ๋ฒ๋ง ํ์ํ ์ ์๋ค. → ์ฆ, ํ์๋ ์คํธ๋ฆผ์ ์์๋ ์๋น๋๋ค!
- ๋ํ ๋ค์ ํ์ํ๋ ค๋ฉด ์ด๊ธฐ ๋ฐ์ดํฐ ์์ค์์ ์๋ก์ด ์คํธ๋ฆผ์ ๋ง๋ค์ด์ผ ํ๋ค
List<String> title = Arrays.asList("Java8", "In", "Action");
Stream<String> s = title.stream();
s.forEach(System.out::println); //title์ ๊ฐ ๋จ์ด๋ฅผ ์ถ๋ ฅ
s.forEach(System.out::println); //IllegalStateException ๋ฐ์
์ธ๋ถ ๋ฐ๋ณต๊ณผ ๋ด๋ถ ๋ฐ๋ณต

- ์ปฌ๋ ์ ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด ์ฌ์ฉ์๊ฐ ์ง์ ์์๋ฅผ ๋ฐ๋ณตํด์ผ ํ๋ค. → ์ธ๋ถ๋ฐ๋ณต
List<String> names = new ArrayList<>();
for(Dish dish: menu) { // ๋ฉ๋ด ๋ฆฌ์คํธ๋ฅผ ์์ฐจ ๋ฐ๋ณตํ๋ค.
names.add(dish.getName()); // ์ด๋ฆ์ ์ถ์ถํด์ ๋ฆฌ์คํธ์ ์ถ๊ฐํ๋ค.
}
Iterator ๊ฐ์ฒด ์ด์ฉ
List<String> names = new ArrayList<>();
Iterator<String> iterator = menu.iterator();
while (iterator.hasNext()) { //๋ช
์์ ๋ฐ๋ณต
Dish dish = iterator.next();
names.add(dish.getName());
}
- ๋ฐ๋ณต์ ์์์ ์ฒ๋ฆฌํ๊ณ ๊ฒฐ๊ณผ ์คํธ๋ฆผ๊ฐ์ ์ด๋๊ฐ์ ์ ์ฅํ๋ค. ์ด๋ค ์์ ์ํํ ์ง๋ง ์ง์ → ๋ด๋ถ๋ฐ๋ณต
List<String> names = menu.stream()
.map(Dish::getName) // map ๋ฉ์๋๋ฅผ getName ๋ฉ์๋๋ก ํ๋ผ๋ฏธํฐํ ํด์ ์๋ฆฌ๋ช
์ถ์ถ
.collect(toList()); // ํ์ดํ๋ผ์ธ์ ์คํ, ๋ฐ๋ณต์ ํ์ X
๋ด๋ถ ๋ฐ๋ณต์ด ๋ ์ข์ ์ด์

- ์์ ์ ํฌ๋ช ํ๊ฒ ๋ณ๋ ฌ๋ก ์ฒ๋ฆฌํ๊ฑฐ๋, ๋ ์ต์ ํ๋ ๋ค์ํ ์์๋ก ์ฒ๋ฆฌํ ์ ์๋ค.
- ์คํธ๋ฆผ์ ๋ด๋ถ ๋ฐ๋ณต์ ๋ฐ์ดํฐ ํํ๊ณผ ํ๋์จ์ด๋ฅผ ํ์ฉํ ๋ณ๋ ฌ์ฑ ๊ตฌํ์ ์๋์ผ๋ก ์ ํํ๋ค.
- ๋ฐ๋ฉด, for-each์ ๊ฐ์ ์ธ๋ถ ๋ฐ๋ณต์์๋ ๋ณ๋ ฌ์ฑ์ ์ค์ค๋ก ๊ด๋ฆฌํด์ผ ํ๋ค. (synchronized)
4. ์คํธ๋ฆผ ์ฐ์ฐ


1. ์ค๊ฐ ์ฐ์ฐ
- ์ค๊ฐ ์ฐ์ฐ์ ๋ค๋ฅธ ์คํธ๋ฆผ์ ๋ฐํํ๋ค ( ์ด์ ์ข ์ง๊ฒน..) → ๊ทธ๋์ ์ด์ด์ง ์ ์๋ ๊ฑฐ
- ์ค๊ฐ ์ฐ์ฐ์ ๊ฒ์ผ๋ฅด๋ค.
- ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ ๋ฟ ์คํธ๋ฆผ์ ์์๋ฅผ ์๋นํ์ง ์๋๋ค.
- ๋ฐ๋ฉด์ ์ต์ข ์ฐ์ฐ์ ์คํธ๋ฆผ์ ์์๋ฅผ ์๋นํ๋ฉฐ ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์ต์ ํํด์ ์ต์ข ๊ฒฐ๊ณผ๋ฅผ ๋์ถํ๋ค.
List<String> names = menu.stream()
.filter(dish -> {
System.out.println("filtering " + dish.getName());
return dish.getCalories() > 300;
}) // ํํฐ๋งํ ์๋ฆฌ๋ช
์ถ๋ ฅ
.map(dish -> {
System.out.println("mapping " + dish.getName());
return dish.getName();
}) // ์ถ์ถํ ์๋ฆฌ๋ช
์ถ๋ ฅ
.limit(3)
.collect(toList());
System.out.println(names);
๊ฒฐ๊ณผ
filtering pork
mapping pork
filtering beef
mapping beef
filtering chicken
mapping chicken
[pork, beef, chicken]
๋ณด๋ฉด filter → map ์ผ๋ก ๋ฐ๋ณต ์ฒ๋ฆฌ ๋๊ณ , ๋ง์ง๋ง์ ํฉ์ณ์ง ํํ๋ฅผ ์ ์ ์๋ค.
์คํธ๋ฆผ์ ๊ฒ์ผ๋ฅธ ํน์ฑ์ด ๋ณด์ธ๋ค.
filter ์์ฒญ ๋ค์ด์ค๋๊น ๊ทธ๋์์ผ ๊ฐ์ ธ์์ ํํฐ๋งํ๊ณ ๋. map๋ ๋ง์ฐฌ๊ฐ์ง๋ค.
์ฌ๊ธฐ์ ์ ์ ์๋ ์ต์ ํ ํจ๊ณผ
- 300 ์นผ๋ก๋ฆฌ๊ฐ ๋๋ ์๋ฆฌ๋ ์ฌ๋ฌ๊ฐ์์ผ๋, ์ฒ์ ์ธ๊ฐ๋ง ์ ํ๋ ์ .
- ์ด๊ฑด limit๊ณผ ์ผํธ ์ํท์ด๋ผ๋ ๊ธฐ๋ฒ ๋๋ถ์ด๋ผ๋๋ฐ ๋๋ ์ง์ฐ ๋ก๋ฉ์ด๋ผ ์์ง ๋ชจ๋ฅธ๋ค
- filter์ map์ ๋ถ๋ช
์๋ก ๋ค๋ฅธ ์ค๊ฐ ์ฐ์ฐ์ด์ง๋ง ํ ๊ณผ์ ์ผ๋ก ๋ณํฉ๋์๋ค
- ํ๋์ (filter → map) ๊ณผ์ ์ผ๋ก ๋ฌถ์
- ์ด ๊ธฐ๋ฒ์ ๋ฃจํ ํจ์ ์ด๋ผ๊ณ ํ๋ค.
2. ์ต์ข ์ฐ์ฐ

์ด๋ฐ์์ผ๋ก ์ต์ข ์ฐ์ฐ์ ์ํด void, List, Integer ๋ฑ ์คํธ๋ฆผ ์ด์ธ์ ๊ฐ์ด ๋ฐํ๋๋ค.
menu.stream().forEach(System.out::println);
3. ์คํธ๋ฆผ ์ด์ฉ
์คํธ๋ฆผ ์ด์ฉ ๊ณผ์
- ์ง์๋ฅผ ์ํํ ๋ฐ์ดํฐ ์์ค(like ์ปฌ๋ ์ )
- ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ฑํ ์ค๊ฐ ์ฐ์ฐ ์ฐ๊ฒฐ
- ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ๋ง๋ค ์ต์ข ์ฐ์ฐ
- ์คํธ๋ฆผ ํ์ดํ๋ผ์ธ์ ๊ฐ๋
์ ๋น๋ ํจํด๊ณผ ๋น์ทํ๋ค!
- ๋น๋ ํจํด์์๋ ํธ์ถ์ ์ฐ๊ฒฐํด์ ์ค์ ์ ๋ง๋ ๋ค(= ์ค๊ฐ ์ฐ์ฐ)
- ๊ทธ๋ฆฌ๊ณ ์ค๋น๋ ์ค์ ์
build()
๋ฉ์๋๋ฅผ ํธ์ถํ๋ค. (= ์ต์ข ์ฐ์ฐ)

* ๋ณธ ํฌ์คํ ์ ๋ชจ๋ ์๋ฐ ์ธ ์ก์ ์ ์ ๋ฆฌํ ๊ธ์ ๋๋ค.