Post

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

์ปฌ๋ ‰์…˜์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ทธ๋ฃนํ™”ํ•˜๊ณ  ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋Œ€๋ถ€๋ถ„์˜ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์ž‘์—…์— ์‚ฌ์šฉ๋œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์™„๋ฒฝํ•œ ์ปฌ๋ ‰์…˜ ๊ด€๋ จ ์—ฐ์‚ฐ์„ ์ง€์›ํ•˜๋ ค๋ฉด ๋ฉ€์—ˆ๋‹ค.

SQL ์งˆ์˜์—์„œ๋Š” ์„ ์–ธํ˜•์œผ๋กœ ์—ฐ์‚ฐ์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ๊ตฌํ˜„์€ ์ž๋™์œผ๋กœ ์ œ๊ณต๋œ๋‹ค.

1
SELECT name FROM dishes WHERE calorie < 400

์ปฌ๋ ‰์…˜์— ์š”์†Œ๊ฐ€ ๋งŽ๋‹ค๋ฉด? ๋ณ‘๋ ฌ๋กœ ์ปฌ๋ ‰์…˜์„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•œ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๋‹จ์ˆœ ๋ฐ˜๋ณต ์ฒ˜๋ฆฌ ์ฝ”๋“œ์— ๋น„ํ•ด ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์€ ๋ณต์žกํ•˜๊ณ  ์–ด๋ ค์šฐ๋ฉฐ ๋””๋ฒ„๊น…์ด ํž˜๋“ค๋‹ค.

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์—์„œ๋Š” ์ด๋Ÿฐ ์„ธ๋ถ€ ๊ตฌํ˜„์€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ(์ŠคํŠธ๋ฆผ) ๋‚ด์—์„œ ๋ชจ๋‘ ์ฒ˜๋ฆฌํ•œ๋‹ค.

1
2
3
4
5
6
List<String> lowCaloricDishesName = 
			menu.stream()
					.filter(d -> d.getCalories() < 400)
					.sorted(comapring(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(comapring(Dish::getCalories))
					.map(Dish::getName)
					.collect(toList());

์ŠคํŠธ๋ฆผ์˜ ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์€ ์†Œํ”„ํŠธ์›จ์–ด๊ณตํ•™์ ์œผ๋กœ ๋‹ค์–‘ํ•œ ์ด๋“์„ ์ค€๋‹ค.

  • ์„ ์–ธํ˜•์œผ๋กœ ์ฝ”๋“œ๋ฅผ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์–ด๋–ป๊ฒŒ ๋™์ž‘์„ ๊ตฌํ˜„ํ• ์ง€ ์ง€์ •ํ•  ํ•„์š” ์—†์ด ๋™์ž‘์˜ ์ˆ˜ํ–‰์„ ์ง€์ •ํ•œ๋‹ค.
    • ์„ ์–ธํ˜• ์ฝ”๋“œ์™€ ๋™์ž‘ ํŒŒ๋ผ๋ฏธํ„ฐํ™”, ๋žŒ๋‹ค๋ฅผ ์ด์šฉํ•˜์—ฌ ์‰ฝ๊ฒŒ ์ฝ”๋“œ ๊ตฌํ˜„์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์š”๊ตฌ์‚ฌํ•ญ์— ์‰ฝ๊ฒŒ ๋Œ€์‘ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋ณต์žกํ•œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ํŒŒ์ดํ”„๋ผ์ธ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.
    • ์—ฌ๋Ÿฌ ์—ฐ์‚ฐ์„ ์—ฐ๊ฒฐํ•ด๋„ ๊ฐ€๋…์„ฑ๊ณผ ๋ช…ํ™•์„ฑ์ด ์œ ์ง€๋œ๋‹ค.

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

๊ฒฐ๊ณผ์ ์œผ๋กœ ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ์—์„œ๋„ ์Šค๋ ˆ๋“œ์™€ ๋ฝ์„ ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง„๋‹ค.

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

์ž๋ฐ” 8 ์ปฌ๋ ‰์…˜์—๋Š” ์ŠคํŠธ๋ฆผ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” stream ๋ฉ”์„œ๋“œ๊ฐ€ ์ถ”๊ฐ€๋๋‹ค.

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

  • ์—ฐ์†๋œ ์š”์†Œ
    • ์ปฌ๋ ‰์…˜์ฒ˜๋Ÿผ ํŠน์ • ์š”์†Œ ํ˜•์‹์œผ๋กœ ์ด๋ฃจ์–ด์ง„ ์—ฐ์†๋œ ๊ฐ’ ์ง‘ํ•ฉ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ œ๊ณตํ•œ๋‹ค.
    • ์ปฌ๋ ‰์…˜์€ ์ž๋ฃŒ๊ตฌ์กฐ์ด๊ธฐ ๋•Œ๋ฌธ์— ์‹œ๊ณต๊ฐ„ ๋ณต์žก์„ฑ๊ณผ ๊ด€๋ จ๋œ ์š”์†Œ ์ €์žฅ ๋ฐ ์ ‘๊ทผ ์—ฐ์‚ฐ์ด ์ฃผ๊ฐ€ ๋œ๋‹ค.
    • ๋ฐ˜๋ฉด ์ŠคํŠธ๋ฆผ์€ ํ‘œํ˜„ ๊ณ„์‚ฐ์‹์ด ์ฃผ๋ฅผ ์ด๋ฃฌ๋‹ค.
    • ์ปฌ๋ ‰์…˜์˜ ์ฃผ์ œ๋Š” ๋ฐ์ดํ„ฐ, ์ŠคํŠธ๋ฆผ์˜ ์ฃผ์ œ๋Š” ๊ณ„์‚ฐ์ด๋‹ค.
  • ์†Œ์Šค
    • ์ŠคํŠธ๋ฆผ์€ ์ปฌ๋ ‰์…˜, ๋ฐฐ์—ด, I/O ์ž์› ๋“ฑ์˜ ๋ฐ์ดํ„ฐ ์ œ๊ณต ์†Œ์Šค๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ๋ฅผ ์†Œ๋น„ํ•œ๋‹ค.
  • ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ ์—ฐ์‚ฐ
    • ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์—์„œ ์ง€์›ํ•˜๋Š” ์—ฐ์‚ฐ๊ณผ DB์™€ ๋น„์Šทํ•œ ์—ฐ์‚ฐ์„ ์ง€์›ํ•œ๋‹ค.
    • filter map reduce find match sort ๋“ฑ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์กฐ์ž‘ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ํŒŒ์ดํ”„๋ผ์ด๋‹
    • ๋Œ€๋ถ€๋ถ„์˜ ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ์€ ์ŠคํŠธ๋ฆผ ์ž์‚ฐ์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ์ด๋Š” ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ๋ผ๋ฆฌ ์—ฐ๊ฒฐํ•ด์„œ ์ปค๋‹ค๋ž€ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.
    • Laziness, Short-Circuiting ๊ฐ™์€ ์ตœ์ ํ™”๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๋‚ด๋ถ€ ๋ฐ˜๋ณต
    • ๋ฐ˜๋ณต์ž๋ฅผ ์ด์šฉํ•˜์—ฌ ๋ช…์‹œ์ ์œผ๋กœ ๋ฐ˜๋ณตํ•˜๋Š” ์ปฌ๋ ‰์…˜๊ณผ ๋‹ฌ๋ฆฌ ์ŠคํŠธ๋ฆผ์€ ๋‚ด๋ถ€ ๋ฐ˜๋ณต์„ ์ง€์›ํ•œ๋‹ค.

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

๋ฐ์ดํ„ฐ๋ฅผ ์–ธ์ œ ๊ณ„์‚ฐํ•˜๋Š๋ƒ๊ฐ€ ์ปฌ๋ ‰์…˜๊ณผ ์ŠคํŠธ๋ฆผ์˜ ๊ฐ€์žฅ ํฐ ์ฐจ์ด๋‹ค.

์ปฌ๋ ‰์…˜์€ ํ˜„์žฌ ์ž๋ฃŒ๊ตฌ์กฐ๊ฐ€ ํฌํ•จํ•˜๋Š” ๋ชจ๋“  ๊ฐ’์„ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅํ•˜๋Š” ์ž๋ฃŒ๊ตฌ์กฐ์ด๋‹ค.

์ฆ‰, ์ปฌ๋ ‰์…˜์˜ ๋ชจ๋“  ์š”์†Œ๋Š” ์ปฌ๋ ‰์…˜์— ์ถ”๊ฐ€ํ•˜๊ธฐ ์ „์— ๊ณ„์‚ฐ๋˜์–ด์•ผ ํ•œ๋‹ค.

์ŠคํŠธ๋ฆผ์€ ์ด๋ก ์ ์œผ๋กœ ์š”์ฒญํ•  ๋•Œ๋งŒ ์š”์†Œ๋ฅผ ๊ณ„์‚ฐํ•˜๋Š” ๊ณ ์ •๋œ ์ž๋ฃŒ๊ตฌ์กฐ๋‹ค.

์ƒ์‚ฐ์ž์™€ ์†Œ๋น„์ž ๊ด€๊ณ„๋ฅผ ํ˜•์„ฑํ•˜๊ณ , ๊ฒŒ์œผ๋ฅด๊ฒŒ ๋งŒ๋“ค์–ด์ง€๋Š” ์ปฌ๋ ‰์…˜๊ณผ ๊ฐ™๋‹ค.

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

์ŠคํŠธ๋ฆผ์€ ํ•œ ๋ฒˆ๋งŒ ํƒ์ƒ‰ํ•  ์ˆ˜ ์žˆ๋‹ค. ํƒ์ƒ‰๋œ ์ŠคํŠธ๋ฆผ์˜ ์š”์†Œ๋Š” ์†Œ๋น„๋œ๋‹ค.

1
2
3
4
List<String> title = Arrays.asList("Java8", "In", "Action");
Stream<String> s = title.stream();
s.forEach(System.out::println);
s.forEach(System.out::println); // throws IllegalStateException

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

  • ์ปฌ๋ ‰์…˜ ์ธํ„ฐํŽ˜์ด์Šค - ์™ธ๋ถ€ ๋ฐ˜๋ณต

์‚ฌ์šฉ์ž๊ฐ€ ์ง์ ‘ ์š”์†Œ๋ฅผ ๋ฐ˜๋ณตํ•ด์•ผ ํ•œ๋‹ค.

1
2
3
4
List<String> names = new ArrayList<>();
for(Dish dish: menu) {
	names.add(dish.getName());
}
  • ์ŠคํŠธ๋ฆผ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ - ๋‚ด๋ถ€ ๋ฐ˜๋ณต

ํ•จ์ˆ˜์— ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ• ์ง€๋งŒ ์ง€์ •ํ•˜๋ฉด ๋ชจ๋“  ๊ฒƒ์ด ์•Œ์•„์„œ ์ฒ˜๋ฆฌ๋œ๋‹ค.

1
2
3
List<String> names = menu.stream()
												.map(Dish::getName)
												.collect(toList());

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

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

์—ฐ๊ฒฐํ•  ์ˆ˜ ์žˆ๋Š” ์ŠคํŠธ๋ฆผ ์—ฐ์‚ฐ

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

์ŠคํŠธ๋ฆผ์„ ๋‹ซ๋Š” ์—ฐ์‚ฐ

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

์ค‘๊ฐ„ ์—ฐ์‚ฐ์€ ๋‹จ๋ง ์—ฐ์‚ฐ์„ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์— ์‹คํ–‰ํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ์•„๋ฌด ์—ฐ์‚ฐ๋„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š๋Š”๋‹ค (Lazy)

1
2
3
4
5
6
7
8
9
10
11
12
13
List<String> names =
		menu.stream()
				.fliter(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
8
// output
filtering:pork
mapping:pork
filtering:beef
mapping:beef
filtering:chicken
mapping:chicken
[pork, beef, chicken]

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

  1. 300 ์นผ๋กœ๋ฆฌ๊ฐ€ ๋„˜๋Š” ์š”๋ฆฌ๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์ง€๋งŒ ์˜ค์ง ์ฒ˜์Œ 3๊ฐœ๋งŒ ์„ ํƒ๋˜์—ˆ๋‹ค. (์‡ผํŠธ์„œํ‚ท)
  2. filter์™€ map์€ ์„œ๋กœ ๋‹ค๋ฅธ ์—ฐ์‚ฐ์ด์ง€๋งŒ ํ•œ ๊ณผ์ •์œผ๋กœ ๋ณ‘ํ•ฉ๋˜์—ˆ๋‹ค. (๋ฃจํ”„ํ“จ์ „)

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

์ตœ์ข… ์—ฐ์‚ฐ์€ ์ŠคํŠธ๋ฆผ ํŒŒ์ดํ”„๋ผ์ธ์—์„œ ๊ฒฐ๊ณผ๋ฅผ ๋„์ถœํ•œ๋‹ค.

๋ณดํ†ต List Integer void ๋“ฑ ์ŠคํŠธ๋ฆผ ์ด์™ธ์˜ ๊ฒฐ๊ณผ๊ฐ€ ๋ฐ˜ํ™˜๋œ๋‹ค.

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

์ŠคํŠธ๋ฆผ์˜ ์ด์šฉ ๊ณผ์ •์€ ์„ธ ๊ฐ€์ง€๋กœ ์š”์•ฝํ•  ์ˆ˜ ์žˆ๋‹ค.

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

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

1
filter, map, limit, sorted, distinct

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

1
forEach, count, collect
This post is licensed under CC BY 4.0 by the author.