Post

๐Ÿน chap4. ์ŠคํŠธ๋ฆผ ์†Œ๊ฐœ

4.1 ์ŠคํŠธ๋ฆผ์ด๋ž€ ๋ฌด์—‡์ธ๊ฐ€?

  • ์ŠคํŠธ๋ฆผ์€ ์ž๋ฐ” 8 API์— ์ƒˆ๋กœ ์ถ”๊ฐ€๋œ ๊ธฐ๋Šฅ์ด๋‹ค.
  • ์ŠคํŠธ๋ฆผ์„ ์‚ฌ์šฉํ•˜๋ฉด ์„ ์–ธํ˜•(์งˆ์˜ ํ‘œํ˜„)์œผ๋กœ ์ปฌ๋ ‰์…˜ ๋ฐ์ดํ„ฐ๋ฅผ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์•„๋„ ๋ฐ์ดํ„ฐ๋ฅผ ํˆฌ๋ช…ํ•˜๊ฒŒ ๋ณ‘๋ ฌ๋กœ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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(dish1.getCalories(), dish2.getCalories());
		}
});
List<String> lowCaloricDishesName = new ArrayList<>();
for(Dish dish: lowCaloricDishes) {
		lowCaloricDishesName.add(dish.getName()); // ์ •๋ ฌ๋œ ๋ฆฌ์ŠคํŠธ๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ฉด์„œ ์š”๋ฆฌ ์ด๋ฆ„ ์„ ํƒ
}

์œ„ ์ฝ”๋“œ์—์„œ๋Š” lowCaloricDishes๋ผ๋Š” โ€˜๊ฐ€๋น„์ง€ ๋ณ€์ˆ˜โ€™(์ปจํ…Œ์ด๋„ˆ ์—ญํ• ๋งŒ ํ•˜๋Š” ์ค‘๊ฐ„ ๋ณ€์ˆ˜)๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. ์ž๋ฐ” 8์—์„œ ์ด๋Ÿฌํ•œ ์„ธ๋ถ€ ๊ตฌํ˜„์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋‚ด์—์„œ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•œ๋‹ค.

๋‹ค์Œ์€ ์ตœ์‹  ์ฝ”๋“œ๋‹ค(์ž๋ฐ” 8)

1
2
3
4
5
6
7
8
import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;
List<String> lowCaloricDishesName = 
						**menu.stream()**
								.filter(d -> d.getCalories() < 400)   // 400์นผ๋กœ๋ฆฌ ์ดํ•˜์˜ ์š”๋ฆฌ ์„ ํƒ
								.sorted(comparing(Dish::getCalories)) // ์นผ๋กœ๋ฆฌ๋กœ ์š”๋ฆฌ ์ •๋ ฌ
								.map(Dish::getName) // ์š”๋ฆฌ๋ช… ์ถ”์ถœ
								.collect(toList()); // ๋ชจ๋“  ์š”๋ฆฌ๋ช…์„ ๋ฆฌ์ŠคํŠธ์— ์ €์žฅ

stream()์„ parallelStream()์œผ๋กœ ๋ฐ”๊พธ๋ฉด ์ด ์ฝ”๋“œ๋ฅผ ๋ฉ€ํ‹ฐ์ฝ”์–ด ์•„ํ‚คํ…์ฒ˜์—์„œ ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
6
List<String> lowCaloricDishesName =
				**menu.parallelStream()**
								.filter(d -> d.getCalories() < 400)  
								.sorted(comparing(Dish::getCalories)) 
								.map(Dish::getName) 
								.collect(toList()); 

๋ฃจํ”„์™€ if ์กฐ๊ฑด๋ฌธ ๋“ฑ์˜ ์ œ์–ด ๋ธ”๋ก์„ ์‚ฌ์šฉํ•ด์„œ ์–ด๋–ป๊ฒŒ ๋™์ž‘์„ ๊ตฌํ˜„ํ• ์ง€ ์ง€์ •ํ•  ํ•„์š” ์—†์ด โ€˜์ €์นผ๋กœ๋ฆฌ์˜ ์š”๋ฆฌ๋งŒ ์„ ํƒํ•˜๋ผโ€™ ๊ฐ™์€ ๋™์ž‘์˜ ์ˆ˜ํ–‰์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์œ„์ฒ˜๋Ÿผ filter, sorted, map, collect ๊ฐ™์€ ์—ฌ๋Ÿฌ ๋นŒ๋”ฉ ๋ธ”๋ก ์—ฐ์‚ฐ์„ ์—ฐ๊ฒฐํ•ด์„œ ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค. ์—ฐ์‚ฐ์„ ํŒŒ์ดํ”„๋ผ์ธ์œผ๋กœ ์—ฐ๊ฒฐํ•ด๋„ ์—ฌ์ „ํžˆ ๊ฐ€๋…์„ฑ๊ณผ ๋ช…ํ™•์„ฑ์ด ์œ ์ง€๋œ๋‹ค. ๊ฐ ์—ฐ์‚ฐ์˜ ๊ฒฐ๊ณผ๋Š” ๋‹ค์Œ ์—ฐ์‚ฐ์œผ๋กœ ์—ฐ๊ฒฐ๋œ๋‹ค.

filter, sorted, map, collect ๊ฐ™์€ ์—ฐ์‚ฐ์€ ๊ณ ์ˆ˜์ค€ ๋นŒ๋”ฉ ๋ธ”๋ก์œผ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์œผ๋ฏ€๋กœ ํŠน์ • ์Šค๋ ˆ๋”ฉ ๋ชจ๋ธ์— ์ œํ•œ๋˜์ง€ ์•Š๊ณ  ์ž์œ ๋กญ๊ฒŒ ์–ด๋–ค ์ƒํ™ฉ์—์„œ๋“  ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. ๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ๊ณผ์ •์„ ๋ณ‘๋ ฌํ™”ํ•˜๋ฉด์„œ ์Šค๋ ˆ๋“œ์™€ ๋ฝ์„ ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋‹ค.

1
2
Map<Dish.Type, List<Dish>> dishesByType = 
		menu.stream().collect(groupingBy(Dish::getType));

์œ„ ์ฝ”๋“œ๋Š” Map ๋‚ด๋ถ€์˜ ํ˜•์‹์— ๋”ฐ๋ผ ์š”๋ฆฌ๋ฅผ ๊ทธ๋ฃนํ™”ํ•œ๋‹ค. ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒฐ๊ณผ๋ฅผ ํฌํ•จํ•  ์ˆ˜ ์žˆ๋‹ค.

1
2
3
4
5
{
		FISH=[prawns,salmon],
		OTHER=[french fries, rice, season fruit, pizza],
		MEAT=[pork, beef, chicken]
}

ํŠน์ง•

  • ์„ ์–ธํ˜• : ๋” ๊ฐ„๊ฒฐํ•˜๊ณ  ๊ฐ€๋…์„ฑ์ด ์ข‹์•„์ง„๋‹ค.
  • ์กฐ๋ฆฝํ•  ์ˆ˜ ์žˆ์Œ : ์œ ์—ฐ์„ฑ์ด ์ข‹์•„์ง„๋‹ค.
  • ๋ณ‘๋ ฌํ™” : ์„ฑ๋Šฅ์ด ์ข‹์•„์ง„๋‹ค.
1
2
3
4
5
6
7
8
9
10
11
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, 300, Dish.Type.FISH),
		new Dish("salmon", false, 450, Dish.Type.FISH)
);

Dish๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ถˆ๋ณ€ํ˜• ํด๋ž˜์Šค๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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;
		}

		@Override
		public String toString() {
				return name;
		}

		public enum Type { MEAT, FISH, OTHER }
}

4.2 ์ŠคํŠธ๋ฆผ ์‹œ์ž‘ํ•˜๊ธฐ

์ŠคํŠธ๋ฆผ : ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์—ฐ์‚ฐ์„ ์ง€์›ํ•˜๋„๋ก ์†Œ์Šค์—์„œ ์ถ”์ถœ๋œ ์—ฐ์†๋œ ์š”์†Œ

  • ์—ฐ์†๋œ ์š”์†Œ
    • ์ปฌ๋ ‰์…˜๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ŠคํŠธ๋ฆผ์€ ํŠน์ • ์š”์†Œ ํ˜•์‹์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ์—ฐ์†๋œ ๊ฐ’ ์ง‘ํ•ฉ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
    • ์ปฌ๋ ‰์…˜์€ ์ž๋ฃŒ๊ตฌ์กฐ์ด๋ฏ€๋กœ (ArrayList๋ฅผ ์‚ฌ์šฉํ• ์ง€ LiskedList๋ฅผ ์‚ฌ์šฉํ• ์ง€) ์‹œ๊ฐ„๊ณผ ๊ณต๊ฐ„์˜ ๋ณต์žก์„ฑ๊ณผ ๊ด€๋ จ๋œ ์š”์†Œ ์ €์žฅ ๋ฐ ์ ‘๊ทผ ์—ฐ์‚ฐ์ด ์ฃผ๋ฅผ ์ด๋ฃฌ๋‹ค.
    • ์ŠคํŠธ๋ฆผ์€ filter, sorted, map์ฒ˜๋Ÿผ ํ‘œํ˜„ ๊ณ„์‚ฐ์‹์ด ์ฃผ๋ฅผ ์ด๋ฃฌ๋‹ค.
    • ์ปฌ๋ ‰์…˜์˜ ์ฃผ์ œ : ๋ฐ์ดํ„ฐ / ์ŠคํŠธ๋ฆผ์˜ ์ฃผ์ œ : ๊ณ„์‚ฐ
  • ์†Œ์Šค
    • ์ปฌ๋ ‰์…˜, ๋ฐฐ์—ด, I/O ์ž์› ๋“ฑ์˜ ๋ฐ์ดํ„ฐ ์ œ๊ณต ์†Œ์Šค๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์†Œ๋น„
    • ์ •๋ ฌ๋œ ์ปฌ๋ ‰์…˜์œผ๋กœ ์ŠคํŠธ๋ฆผ์„ ์ƒ์„ฑํ•˜๋ฉด ์ •๋ ฌ์ด ๊ทธ๋Œ€๋กœ ์œ ์ง€๋œ๋‹ค.
  • ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์—ฐ์‚ฐ
    • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ์ผ๋ฐ˜์ ์œผ๋กœ ์ง€์›ํ•˜๋Š” ์—ฐ์‚ฐ๊ณผ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์™€ ๋น„์Šทํ•œ ์—ฐ์‚ฐ ์ง€์›

      ex) filter, map, reduce, find, match, sort

    • ์ˆœ์ฐจ์  ๋˜๋Š” ๋ณ‘๋ ฌ์ ์œผ๋กœ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ํŒŒ์ดํ”„๋ผ์ด๋‹
    • ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ๋ผ๋ฆฌ ์—ฐ๊ฒฐํ•ด์„œ ์ปค๋‹ค๋ž€ ํŒŒ์ดํ”„ ๋ผ์ธ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ์ŠคํŠธ๋ฆผ ์ž์‹ ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋•๋ถ„์— ์ตœ์ ํ™” ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.
    • ์—ฐ์‚ฐ ํŒŒ์ดํ”„๋ผ์ธ์€ ๋ฐ์ดํ„ฐ ์†Œ์Šค์— ์ ์šฉํ•˜๋Š” ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์งˆ์˜์™€ ๋น„์Šทํ•˜๋‹ค.
  • ๋‚ด๋ถ€ ๋ฐ˜๋ณต
    • ๋ฐ˜๋ณต์ž๋ฅผ ์ด์šฉํ•ด์„œ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ˜๋ณตํ•˜๋Š” ์ปฌ๋ ‰์…˜๊ณผ ๋‹ฌ๋ฆฌ ์ŠคํŠธ๋ฆผ์€ ๋‚ด๋ถ€ ๋ฐ˜๋ณต์„ ์ง€์›ํ•œ๋‹ค.
1
2
3
4
5
6
7
8
import static java.util.stream.Collectors.toList;
List<String> threeHighCaloricDishNames =
		menu.stream()  // ๋ฉ”๋‰ด(์š”๋ฆฌ ๋ฆฌ์ŠคํŠธ)์—์„œ ์ŠคํŠธ๋ฆผ์„ ์–ป๋Š”๋‹ค.
				.filter(dish -> dish.getCalories() > 300) // ๊ณ ์นผ๋กœ๋ฆฌ ์š”๋ฆฌ ํ•„ํ„ฐ๋ง
				.map(Dish::getName)                       // ์š”๋ฆฌ๋ช… ์ถ”์ถœ
				.limit(3)                                 // ์„ ์ฐฉ์ˆœ ์„ธ ๊ฐœ๋งŒ ์„ ํƒ
				.collect(toList());                       // ๊ฒฐ๊ณผ๋ฅผ ๋‹ค๋ฅธ ๋ฆฌ์ŠคํŠธ๋กœ ์ €์žฅ
System.out.println(threeHighCaloricDishNames);    // ๊ฒฐ๊ณผ๋Š” [pork, beef, chicken]

๋ฐ์ดํ„ฐ ์†Œ์Šค๋Š” ์š”๋ฆฌ ๋ฆฌ์ŠคํŠธ(๋ฉ”๋‰ด)์ด๋‹ค.

  • filter
    • ๋žŒ๋‹ค๋ฅผ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ํŠน์ • ์š”์†Œ๋ฅผ ์ œ์™ธ์‹œํ‚จ๋‹ค.
    • d โ†’ d.getCalories() > 300์ด๋ผ๋Š” ๋žŒ๋‹ค๋ฅผ ์ „๋‹ฌํ•ด์„œ 300 ์นผ๋กœ๋ฆฌ ์ด์ƒ์˜ ์š”๋ฆฌ๋ฅผ ์„ ํƒํ•œ๋‹ค.
  • map
    • ๋žŒ๋‹ค๋ฅผ ์ด์šฉํ•ด์„œ ํ•œ ์š”์†Œ๋ฅผ ๋‹ค๋ฅธ ์š”์†Œ๋กœ ๋ณ€ํ™˜ํ•˜๊ฑฐ๋‚˜ ์ •๋ณด๋ฅผ ์ถ”์ถœํ•œ๋‹ค.
    • ๋ฉ”์„œ๋“œ ์ฐธ์กฐ Dish::getName (๋žŒ๋‹ค ํ‘œํ˜„์‹์œผ๋กœ๋Š” d โ†’ d.getName())์„ ์ „๋‹ฌํ•ด์„œ ๊ฐ๊ฐ์˜ ์š”๋ฆฌ๋ช…์„ ์ถ”์ถœํ•œ๋‹ค.
  • limit
    • ์ •ํ•ด์ง„ ๊ฐœ์ˆ˜ ์ด์ƒ์˜ ์š”์†Œ๊ฐ€ ์ŠคํŠธ๋ฆผ์— ์ €์žฅ๋˜์ง€ ๋ชปํ•˜๊ฒŒ ์ŠคํŠธ๋ฆผ ํฌ๊ธฐ๋ฅผ ์ถ•์†Œ truncateํ•œ๋‹ค.
  • collect
    • ์ŠคํŠธ๋ฆผ์„ ๋‹ค๋ฅธ ํ˜•์‹์œผ๋กœ ๋ณ€ํ™˜ํ•œ๋‹ค. (ex. ์ŠคํŠธ๋ฆผ์„ ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜)
    • collect๊ฐ€ ๋‹ค์–‘ํ•œ ๋ณ€ํ™˜ ๋ฐฉ๋ฒ•์„ ์ธ์ˆ˜๋กœ ๋ฐ›์•„ ์ŠคํŠธ๋ฆผ์— ๋ˆ„์ ๋œ ์š”์†Œ๋ฅผ ํŠน์ • ๊ฒฐ๊ณผ๋กœ ๋ณ€ํ™˜์‹œํ‚ค๋Š” ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค.

4.3 ์ŠคํŠธ๋ฆผ๊ณผ ์ปฌ๋ ‰์…˜

์ปฌ๋ ‰์…˜๊ณผ ์ŠคํŠธ๋ฆผ์˜ ์ฐจ์ด

  • ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๋•Œ(์‹œ๊ฐ„)์˜ ์ฐจ์ด
    • ์ปฌ๋ ‰์…˜ : ํ˜„์žฌ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ํฌํ•จํ•˜๋Š” ๋ชจ๋“  ๊ฐ’์„ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ

      โ†’ ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  ์š”์†Œ๋Š” ์ปฌ๋ ‰์…˜์— ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— ๊ณ„์‚ฐ๋˜์–ด์•ผ ํ•จ

    • ์ŠคํŠธ๋ฆผ : ์š”์ฒญํ•  ๋•Œ๋งŒ ์š”์†Œ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๊ณ ์ •๋œ ์ž๋ฃŒ๊ตฌ์กฐ(์ŠคํŠธ๋ฆผ์—๋Š” ์š”์†Œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ฑฐ๋‚˜ ์ œ๊ฑฐํ• ์ˆ˜ ์—†๋‹ค)

      โ†’ ์‚ฌ์šฉ์ž๊ฐ€ ์š”์ฒญํ•˜๋Š” ๊ฐ’๋งŒ ์ŠคํŠธ๋ฆผ์—์„œ ์ถ”์ถœํ•จ

4.3.1 ๋”ฑ ํ•œ ๋ฒˆ๋งŒ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค

๋ฐ˜๋ณต์ž์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ŠคํŠธ๋ฆผ๋„ ํ•œ ๋ฒˆ๋งŒ ํƒ์ƒ‰ ๊ฐ€๋Šฅํ•˜๋‹ค.

๋ฐ˜๋ณต์ž์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ํ•œ ๋ฒˆ ํƒ์ƒ‰ํ•œ ์š”์†Œ๋ฅผ ๋‹ค์‹œ ํƒ์ƒ‰ํ•˜๋ ค๋ฉด ์ดˆ๊ธฐ ๋ฐ์ดํ„ฐ ์†Œ์Šค์—์„œ ์ƒˆ๋กœ์šด ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. โ†’ ๋งŒ์•ฝ ๋ฐ์ดํ„ฐ ์†Œ์Šค๊ฐ€ I/O ์ฑ„๋„์ด๋ผ๋ฉด ์†Œ์Šค๋ฅผ ๋ฐ˜๋ณต ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์œผ๋ฏ€๋กœ ์ƒˆ๋กœ์šด ์ŠคํŠธ๋ฆผ์„ ๋งŒ๋“ค ์ˆ˜ ์—†๋‹ค.

1
2
3
4
5
List<String> title = Arrays.asList("Java8", "In", "Action");
Stream<String> s = title.stream();
s.forEach(System.out::println); // title์˜ ๊ฐ ๋‹จ์–ด๋ฅผ ์ถœ๋ ฅ
s.forEach(System.out::println); 
// -> java.lang.IllegalStateException: ์ŠคํŠธ๋ฆผ์ด ์ด๋ฏธ ์†Œ๋น„๋˜์—ˆ๊ฑฐ๋‚˜ ๋‹ซํž˜

์ŠคํŠธ๋ฆผ์€ ๋‹จ ํ•œ ๋ฒˆ๋งŒ ์†Œ๋น„ํ•  ์ˆ˜ ์žˆ๋‹ค!

4.3.2 ์™ธ๋ถ€ ๋ฐ˜๋ณต๊ณผ ๋‚ด๋ถ€ ๋ฐ˜๋ณต

  • ์ปฌ๋ ‰์…˜ : ์™ธ๋ถ€ ๋ฐ˜๋ณต, ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์š”์†Œ๋ฅผ ๋ฐ˜๋ณตํ•ด์•ผํ•จ(ex. for-each)

    1
    2
    3
    4
    
      List<String> names = new ArrayList<>();
      for(Dish dish: menu) { // ๋ฉ”๋‰ด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋ช…์‹œ์ ์œผ๋กœ ์ˆœ์ฐจ ๋ฐ˜๋ณตํ•œ๋‹ค.
      		names.add(dish.getName()); // ์ด๋ฆ„์„ ์ถ”์ถœํ•ด์„œ ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ํ•œ๋‹ค.
      }
    
    1
    2
    3
    4
    5
    6
    
      List<String> names = new ArrayList<>();
      Iterator<String> iterator = menu.iterator();
      while(iterator.hasNext()) { // ๋ช…์‹œ์  ๋ฐ˜๋ณต
      		Dish dish = iterator.next();
      		names.add(dish.getName());
      }
    
  • ์ŠคํŠธ๋ฆผ : ๋‚ด๋ถ€ ๋ฐ˜๋ณต, ํ•จ์ˆ˜์— ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ• ์ง€๋งŒ ์ง€์ •ํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์ด ์•Œ์•„์„œ ์ฒ˜๋ฆฌ๋จ

    1
    2
    3
    
      List<String> name = menu.stream()
      												.map(Dish::getName) // map ๋ฉ”์„œ๋“œ๋ฅผ getName ๋ฉ”์„œ๋“œ๋กœ ํŒŒ๋ผ๋ฏธํ„ฐํ™”ํ•ด์„œ ์š”๋ฆฌ๋ช… ์ถ”์ถœ
      												.collect(toList()); // ํŒŒ์ดํ”„๋ผ์ธ์„ ์‹คํ–‰ํ•œ๋‹ค. ๋ฐ˜๋ณต์ž ํ•„์š”์—†๋‹ค. 
    

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

      ์ปฌ๋ ‰์…˜์€ ์Šค์Šค๋กœ ๊ด€๋ฆฌํ•ด์•ผํ•œ๋‹ค.(ํฌ๊ธฐํ•˜๋˜์ง€ synchronized๋กœ ์‚ฌ์šฉํ•˜๋˜์ง€)

  • Quiz. ์™ธ๋ถ€ ๋ฐ˜๋ณต vs ๋‚ด๋ถ€ ๋ฐ˜๋ณต

    ์ŠคํŠธ๋ฆผ ๋™์ž‘์„ ์‚ฌ์šฉํ•ด ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ๋ฆฌํŒฉํ† ๋ง ํ•ด๋ณด์ž.

    1
    2
    3
    4
    5
    6
    7
    8
    
      List<String> highCaloricDishes = new ArrayList<>();
      Iterator<String> iterator = menu.iterator();
      while(iterator.hasNext()) {
      		Dish dish = iterator.next();
      		if(dish.getCalories() > 300) {
      				highCaloricDishes.add(d.getName());
      		}
      }
    
    • ์ •๋‹ต

      1
      2
      3
      4
      5
      
        List<String> highCaloricDishes =
        						menu.stream()
        								.filter(d -> d.getCalories() > 300)
        								.map(Dish::getName)
        								.collect(toList());
      

4.4 ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ

1
2
3
4
5
List<String> names = menu.stream() // ์š”๋ฆฌ ๋ฆฌ์ŠคํŠธ์—์„œ ์ŠคํŠธ๋ฆผ ์–ป๊ธฐ
												 .filter(dish -> dish.getCalories() > 300) // ์ค‘๊ฐ„ ์—ฐ์‚ฐ
												 .map(Dish::getName) // ์ค‘๊ฐ„ ์—ฐ์‚ฐ
												 .limit(3)           // ์ค‘๊ฐ„ ์—ฐ์‚ฐ
												 .collect(toList()); // ์ŠคํŠธ๋ฆผ์„ ๋ฆฌ์ŠคํŠธ๋กœ ๋ณ€ํ™˜

์œ„ ์˜ˆ์ œ์—์„œ ์—ฐ์‚ฐ์„ ๋‘ ๊ทธ๋ฃน์œผ๋กœ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๋‹ค.

  • ์ค‘๊ฐ„ ์—ฐ์‚ฐ : filter, map, limit์€ ์„œ๋กœ ์—ฐ๊ฒฐ๋˜์–ด ํŒŒ์ดํ”„๋ผ์ธ์„ ํ˜•์„ฑ
  • ์ตœ์ข… ์—ฐ์‚ฐ : collect๋กœ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‹คํ–‰ํ•œ ๋‹ค์Œ ๋‹ซ๊ธฐ

4.4.1 ์ค‘๊ฐ„ ์—ฐ์‚ฐ

filter๋‚˜ sorted ๊ฐ™์€ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์€ ๋‹ค๋ฅธ ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ค‘๊ฐ„ ์—ฐ์‚ฐ์˜ ํŠน์ง•์€ ๋‹จ๋ง ์—ฐ์‚ฐ์„ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์— ์‹คํ–‰ํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์•„๋ฌด ์—ฐ์‚ฐ๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒƒ, ์ฆ‰ ๊ฒŒ์œผ๋ฅด๋‹ค๋Š” ๊ฒƒ์ด๋‹ค. ์ค‘๊ฐ„ ์—ฐ์‚ฐ์„ ํ•ฉ์นœ ๋‹ค์Œ์— ํ•ฉ์ณ์ง„ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์„ ์ตœ์ข… ์—ฐ์‚ฐ์œผ๋กœ ํ•œ ๋ฒˆ์— ์ฒ˜๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

1
2
3
4
5
6
7
8
9
10
11
12
13
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);
1
2
3
4
5
6
7
filtering:pork
mapping:pork
filtering:beef
mapping:beef
filtering:chicken
mapping:chicken
[pork, beef, chicken]

์ŠคํŠธ๋ฆผ์˜ ๊ฒŒ์œผ๋ฅธ(lazy) ํŠน์„ฑ ๋•Œ๋ฌธ์— ๋ช‡ ๊ฐ€์ง€ ์ตœ์ ํ™” ํšจ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

  • 300 ์นผ๋กœ๋ฆฌ๊ฐ€ ๋„˜๋Š” ์š”๋ฆฌ๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์ง€๋งŒ ์˜ค์ง ์ฒ˜์Œ 3๊ฐœ๋งŒ ์„ ํƒ๋˜์—ˆ๋‹ค.

    โ†’ ์ด๋Š” limit ์—ฐ์‚ฐ ๊ทธ๋ฆฌ๊ณ  ์‡ผํŠธ์„œํ‚ท์ด๋ผ ๋ถˆ๋ฆฌ๋Š” ๊ธฐ๋ฒ• ๋•๋ถ„์ด๋‹ค.

  • filter์™€ map์€ ์„œ๋กœ ๋‹ค๋ฅธ ์—ฐ์‚ฐ์ด์ง€๋งŒ ํ•œ ๊ณผ์ •์œผ๋กœ ๋ณ‘ํ•ฉ๋˜์—ˆ๋‹ค.

    โ†’ ์ด ๊ธฐ๋ฒ•์€ ๋ฃจํ”„ ํ“จ์ „์ด๋ผ๊ณ  ํ•œ๋‹ค.

4.4.2 ์ตœ์ข… ์—ฐ์‚ฐ

์ตœ์ข… ์—ฐ์‚ฐ์€ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ๊ฒฐ๊ณผ๋ฅผ ๋„์ถœํ•œ๋‹ค. ๋ณดํ†ต ์ตœ์ข… ์—ฐ์‚ฐ์— ์˜ํ•ด List, Integer, void ๋“ฑ ์ŠคํŠธ๋ฆผ ์ด์™ธ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

๋‹ค์Œ์€ void ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

1
menu.stream().forEach(System.out::println);
  • Quiz. ์ค‘๊ฐ„ ์—ฐ์‚ฐ๊ณผ ์ตœ์ข… ์—ฐ์‚ฐ

    ๋‹ค์Œ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ์ค‘๊ฐ„ ์—ฐ์‚ฐ๊ณผ ์ตœ์ข… ์—ฐ์‚ฐ์„ ๊ตฌ๋ณ„ํ•˜์‹œ์˜ค.

    1
    2
    3
    4
    5
    
      long count = menu.stream()
      								 .filter(d -> d.getCalories() > 300)
      								 .distinct()
      								 .limit(3)
      								 .count();
    
    • ์ •๋‹ต

      ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์˜ ๋งˆ์ง€๋ง‰ ์—ฐ์‚ฐ count๋Š” ์ŠคํŠธ๋ฆผ์ด ์•„๋‹Œ long์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ๋”ฐ๋ผ์„œ count๋Š” ์ตœ์ข… ์—ฐ์‚ฐ์ด๋‹ค. filter, distinct, limit๋Š” ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋ฉฐ ์„œ๋กœ ์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด๋“ค์€ ์ค‘๊ฐ„ ์—ฐ์‚ฐ์ด๋‹ค.

4.4.3 ์ŠคํŠธ๋ฆผ ์ด์šฉํ•˜๊ธฐ

์ŠคํŠธ๋ฆผ์˜ ์ด์šฉ ๊ณผ์ •์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์งˆ์˜๋ฅผ ์ˆ˜ํ–‰ํ•  (์ปฌ๋ ‰์…˜ ๊ฐ™์€) ๋ฐ์ดํ„ฐ ์†Œ์Šค
  • ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•  ์ค‘๊ฐ„ ์—ฐ์‚ฐ ์—ฐ๊ฒฐ
  • ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์„ ์‹คํ–‰ํ•˜๊ณ  ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค ์ตœ์ข… ์—ฐ์‚ฐ

[ ์ค‘๊ฐ„ ์—ฐ์‚ฐ ]

์—ฐ์‚ฐํ˜•์‹๋ฐ˜ํ™˜ ํ˜•์‹์—ฐ์‚ฐ์˜ ์ธ์ˆ˜ํ•จ์ˆ˜ ๋””์Šคํฌ๋ฆฝํ„ฐ
filter์ค‘๊ฐ„ ์—ฐ์‚ฐStreamPredicateT โ†’ boolean
map์ค‘๊ฐ„ ์—ฐ์‚ฐStreamFunction<T, R>T โ†’ R
limit์ค‘๊ฐ„ ์—ฐ์‚ฐStreamย ย 
sorted์ค‘๊ฐ„ ์—ฐ์‚ฐStreamComparator(T, T) โ†’ int
distinct์ค‘๊ฐ„ ์—ฐ์‚ฐStreamย ย 

[ ์ตœ์ข… ์—ฐ์‚ฐ ]

์—ฐ์‚ฐํ˜•์‹๋ฐ˜ํ™˜ ํ˜•์‹๋ชฉ์ 
forEach์ตœ์ข… ์—ฐ์‚ฐvoid์ŠคํŠธ๋ฆผ์˜ ๊ฐ ์š”์†Œ๋ฅผ ์†Œ๋น„ํ•˜๋ฉด์„œ ๋žŒ๋‹ค๋ฅผ ์ ์šฉํ•œ๋‹ค.
count์ตœ์ข… ์—ฐ์‚ฐlong(generic)์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ ๊ฐœ์ˆ˜๋ฅผ ๋ฐ˜ํ™˜ํ•œ๋‹ค.
collect์ตœ์ข… ์—ฐ์‚ฐย ์ŠคํŠธ๋ฆผ์„ ๋ฆฌ๋“€์Šคํ•ด์„œ ๋ฆฌ์ŠคํŠธ, ๋งต, ์ •์ˆ˜ ํ˜•์‹์˜ ์ปฌ๋ ‰์…˜์„ ๋งŒ๋“ ๋‹ค.
This post is licensed under CC BY 4.0 by the author.