From a65bac2406bff3d60f48e4bcc4d0e1910fe4c53e Mon Sep 17 00:00:00 2001 From: daadaadaah Date: Wed, 31 Jan 2024 17:21:49 +0900 Subject: [PATCH 1/4] =?UTF-8?q?[=EB=AA=A8=EB=8D=98=20=EC=9E=90=EB=B0=94=20?= =?UTF-8?q?=EC=9D=B8=20=EC=95=A1=EC=85=98]=20=EA=B8=B0=EC=A1=B4=20Java=207?= =?UTF-8?q?=20=EC=BD=94=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mordernjavainactionpractice/Dish.java | 53 +++++++++++++++++++ ...ModernJavaInActionPracticeApplication.java | 34 +++++++++++- 2 files changed, 85 insertions(+), 2 deletions(-) create mode 100644 modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/Dish.java diff --git a/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/Dish.java b/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/Dish.java new file mode 100644 index 00000000..3f42faf7 --- /dev/null +++ b/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/Dish.java @@ -0,0 +1,53 @@ +package com.example.mordernjavainactionpractice; + +import java.util.Arrays; +import java.util.List; + +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 } + + @Override + public String toString() { + return name; + } + + public static final List 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)); +} \ No newline at end of file diff --git a/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java b/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java index 882eca2f..79cfc684 100644 --- a/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java +++ b/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java @@ -1,12 +1,42 @@ package com.example.mordernjavainactionpractice; -import org.springframework.boot.SpringApplication; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class ModernJavaInActionPracticeApplication { public static void main(String[] args) { - SpringApplication.run(ModernJavaInActionPracticeApplication.class, args); + getLowCaloricDishesNamesInJava7(Dish.menu).forEach(System.out::println); + } + + // Java 7 + public static List getLowCaloricDishesNamesInJava7(List dishes){ + List lowCaloricDishes = new ArrayList<>(); + + // 누적자로 요소 피러링 : 400 이하의 요리 담기 + for(Dish d: dishes){ + if(d.getCalories() < 400){ + lowCaloricDishes.add(d); + } + } + + // 익명 클래스로 요리 정렬 : 칼로리 순으로 정렬 + Collections.sort(lowCaloricDishes, new Comparator() { + public int compare(Dish d1, Dish d2){ + return Integer.compare(d1.getCalories(), d2.getCalories()); + } + }); + + // 정려된 리스트를 처리하면서 요리 이름 선택 : 요리 이름만 담기 + List lowCaloricDishesName = new ArrayList<>(); + for(Dish d: lowCaloricDishes){ + lowCaloricDishesName.add(d.getName()); + } + + return lowCaloricDishesName; } } From 1159019415ef726b3d2082064db76037afa193ee Mon Sep 17 00:00:00 2001 From: daadaadaah Date: Wed, 31 Jan 2024 17:23:01 +0900 Subject: [PATCH 2/4] =?UTF-8?q?[=EB=AA=A8=EB=8D=98=20=EC=9E=90=EB=B0=94=20?= =?UTF-8?q?=EC=9D=B8=20=EC=95=A1=EC=85=98]=20Java=208=20=EC=BD=94=EB=93=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...ModernJavaInActionPracticeApplication.java | 40 +++++-------------- 1 file changed, 11 insertions(+), 29 deletions(-) diff --git a/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java b/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java index 79cfc684..7ba59323 100644 --- a/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java +++ b/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java @@ -1,8 +1,8 @@ package com.example.mordernjavainactionpractice; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; +import static java.util.Comparator.comparing; +import static java.util.stream.Collectors.toList; + import java.util.List; import org.springframework.boot.autoconfigure.SpringBootApplication; @@ -10,33 +10,15 @@ public class ModernJavaInActionPracticeApplication { public static void main(String[] args) { - getLowCaloricDishesNamesInJava7(Dish.menu).forEach(System.out::println); + getLowCaloricDishesNamesInJava8(Dish.menu).forEach(System.out::println); } - // Java 7 - public static List getLowCaloricDishesNamesInJava7(List dishes){ - List lowCaloricDishes = new ArrayList<>(); - - // 누적자로 요소 피러링 : 400 이하의 요리 담기 - for(Dish d: dishes){ - if(d.getCalories() < 400){ - lowCaloricDishes.add(d); - } - } - - // 익명 클래스로 요리 정렬 : 칼로리 순으로 정렬 - Collections.sort(lowCaloricDishes, new Comparator() { - public int compare(Dish d1, Dish d2){ - return Integer.compare(d1.getCalories(), d2.getCalories()); - } - }); - - // 정려된 리스트를 처리하면서 요리 이름 선택 : 요리 이름만 담기 - List lowCaloricDishesName = new ArrayList<>(); - for(Dish d: lowCaloricDishes){ - lowCaloricDishesName.add(d.getName()); - } - - return lowCaloricDishesName; + // Java 8 + public static List getLowCaloricDishesNamesInJava8(List dishes) { + return dishes.stream() + .filter(d -> d.getCalories() < 400) // 400 이하의 요리 담기 + .sorted(comparing(Dish::getCalories)) // 칼로리 순으로 정렬 + .map(Dish::getName) // 요리 이름만 담기 + .collect(toList()); } } From 6319c6ef1fcf289f4f45458a9e90051e117abe59 Mon Sep 17 00:00:00 2001 From: daadaadaah Date: Wed, 31 Jan 2024 17:25:54 +0900 Subject: [PATCH 3/4] =?UTF-8?q?[=EB=AA=A8=EB=8D=98=20=EC=9E=90=EB=B0=94=20?= =?UTF-8?q?=EC=9D=B8=20=EC=95=A1=EC=85=98]=20Java=208=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20-=20=EB=A9=80=ED=8B=B0=EC=BD=94=EC=96=B4=20=EC=95=84?= =?UTF-8?q?=ED=82=A4=ED=85=8C=EC=B2=98=EC=97=90=EC=84=9C=20=EB=B3=91?= =?UTF-8?q?=EB=A0=AC=EB=A1=9C=20=EC=8B=A4=ED=96=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ModernJavaInActionPracticeApplication.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java b/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java index 7ba59323..0b5431e4 100644 --- a/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java +++ b/modern_java_in_action/mordern-java-in-action-practice/src/main/java/com/example/mordernjavainactionpractice/ModernJavaInActionPracticeApplication.java @@ -15,7 +15,7 @@ public static void main(String[] args) { // Java 8 public static List getLowCaloricDishesNamesInJava8(List dishes) { - return dishes.stream() + return dishes.parallelStream() .filter(d -> d.getCalories() < 400) // 400 이하의 요리 담기 .sorted(comparing(Dish::getCalories)) // 칼로리 순으로 정렬 .map(Dish::getName) // 요리 이름만 담기 From 1a4aff45ff20e2d3c505167d62878cf71173481d Mon Sep 17 00:00:00 2001 From: daadaadaah Date: Thu, 1 Feb 2024 15:02:10 +0900 Subject: [PATCH 4/4] =?UTF-8?q?[=EB=AA=A8=EB=8D=98=20=EC=9E=90=EB=B0=94=20?= =?UTF-8?q?=EC=9D=B8=20=EC=95=A1=EC=85=98]=204=EC=9E=A5=20=EC=A0=95?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mordern-java-in-action-practice/ch4.md | 96 +++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 modern_java_in_action/mordern-java-in-action-practice/ch4.md diff --git a/modern_java_in_action/mordern-java-in-action-practice/ch4.md b/modern_java_in_action/mordern-java-in-action-practice/ch4.md new file mode 100644 index 00000000..ef7e5d9a --- /dev/null +++ b/modern_java_in_action/mordern-java-in-action-practice/ch4.md @@ -0,0 +1,96 @@ +# Chapter 4. 스트림 소개 +## 스트림이란 무엇인가요? + + +## 스트림을 사용하면 어떤 점이 좋은가요? + + + + +------------------------------------------ + + + +## 4.1 스트림이란 무엇인가요? +- 스트림을 이용하면 선언형으로 컬렉션 데이터를 처리할 수 있다. -> 일단 스트림이 데이터 컬렉션 반복을 멋지게 처리하는 기능이라고 생각하자! +- 또한, 스트림을 이용하면 멀티스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수 있다. + +### 스트림의 특징에 따른 장점 +#### 1. 선언형 : 더 간결하고 가독성이 좋아진다. +#### 2. 조립할 수 있음 : 유연성이 좋아진다. +- 여러 빌딩 블록 연산(filter, sorted, map, collect 등)을 연결해서 복잡한 데이터 처리 파이프라인을 만들 수 있다. +- 여러 연산을 파이프라인으로 연결해도 여전히 가독성과 명확성이 유지된다. +#### 3. 병렬화 : 성능이 좋아진다. + +## 4.2 스트림 시작하기 +- 스트림이란 `데이터 처리 연산을 지원하도록 / 소스에서 추출된 / 연속된 요소`로 정의할 수 있다. + #### 1. 연속된 요소 + #### 2. 소스 + #### 3. 데이터 처리 연산 + +- 스트림에는 다음과 같은 2가지 중요 특징이 있다. + #### 특징 1. 파이프라이닝 + - ㄹㄹ + + #### 특징 2. 내부 반복 + + + +## 4.3 스트림과 컬렉션 + + +### 4.3.1 딱 한번만 탐색할 수 있다. + + +### 4.3.2 외부 반복과 내부 반복 +- 컬렉션 인터페이스를 사용하면, 사용자가 지겁 요소를 반복해야 하는 `외부 요소`를 사용한다. +- 반면, 스트림 라이브러리는 (반복을 알아서 처리하고 결과 스트림값을 어딘가에 저장해주는) `내부 반복`을 사용한다. +- 함수에 어떤 작업을 수행할지만 지정하면 모든 것이 알아서 처리된다. + + + +## 4.4 스트림 연산 +- `java.util.stream.Stream` 인터페이스는 많은 연산을 정의하는데, 크게 2가지로 구분할 수 있다. +- 연결할 수 있는 스트림 연산을 `중간 연산`이라고 하며, 스트림을 닫는 연산을 `최종 연산`이라고 한다. +- 즉, `filter`, `map`, `limit` 는 서로 연결되어 파이프라인을 형성하고, `collect`로 파이프라인을 실행한 다음에 닫는다. + +```java +List names = menu.stream() // 요리 리스트에서 스트림 얻기 + .filter(dish -> dish.getCalories() > 300) // 중간 연산 + .map(Dish::getName) // 중간 연산 + .limit(3) // 중간 연산 + .collect(toList()); // 스트림을 리스트로 변환 +``` + +### 4.4.1 중간 연산 +- 중간 연산은 다른 스트림을 반환한다. 따라서, 여러 중간 연산을 연결해서 질의를 만들 수 있다. +- 중간 연산의 특징은 단말 연산을 스트림 파이프라인에 실행하기 전까지는 아무 연산도 수행하지 않는다는 것이다. +- 즉 Lazy 하다는 것이다. 중간 연산을 합친 다음에 중간 연산을 최종 연산으로 한 번에 처리하기 때문이다. +- 스트림의 게으른 특성 덕분에 몇가지 최적화 효과를 얻을 수 있었다. +#### 최적화 효과 1. limit 연산 그리고 쇼트 서킷 +- 300칼로리가 넘은 요리는 여러 개지만, 오직 처음 3개만 선택되었다. +#### 최적화 효과 2. 루프 퓨전(loop fusion) +- filter와 map은 서로 다른 연산이지만 한 과정으로 병합되었다. + + +### 4.4.2 최종 연산 +- 최종 연산은 스트림 파이프라인에서 결과를 도출한다. +- 보통 최종 연산에 의해 List, Integer, void 등 스트림 이외의 결과가 반환된다. + +### 4.4.3 스트림 이용하기 +- 스트림 이용 과정은 다음과 같이 3가지로 요약할 수 있다. +1. 질의를 수행할 (컬렉션 같은) `데이터 소스` +2. 스트림 파이프라인을 구성할 `중간 연산` 연결 +3. 스트림 파이프라인을 실행하고 결과를 만들 `최종 연산` + + + + + + + + + + + +