├── .gitignore
├── LICENSE
├── README.md
├── YouTube-social-icon_red_24px.png
├── build.gradle
├── pom.xml
├── settings.gradle
└── src
├── main
└── java
│ └── cc
│ └── kevinlee
│ └── modernjava
│ ├── e01
│ ├── LambdaExample.java
│ ├── OopAndFpExamples.java
│ ├── OopExample.java
│ └── WhyJava8.java
│ ├── e02_function
│ └── FunctionExamples.java
│ ├── e03_consumer
│ └── ConsumerExamples.java
│ ├── e04_predicate
│ └── PredicateExamples.java
│ ├── e05_supplier
│ └── SupplierExamples.java
│ ├── e06_custom_functionalinterface
│ └── CustomFunctionalInterfaceExamples.java
│ ├── e07_functionalinterface_examples
│ └── FunctionalInterfaceExamples.java
│ ├── e08_01_stream_prelude
│ └── StreamPrelude.java
│ ├── e08_02_identity
│ └── IdentityExamples.java
│ ├── e08_03_stream_01
│ └── StreamExamples1.java
│ ├── e08_03_stream_02
│ └── StreamExamples2.java
│ ├── e08_03_stream_03
│ └── StreamExamples3.java
│ ├── e08_03_stream_04
│ └── StreamExamples4.java
│ ├── e08_03_stream_05_parallel
│ ├── StreamExamples5Parallel.java
│ ├── StreamExamples5ParallelPerformance.java
│ └── StreamExamples5ParallelPerformancePractical.java
│ ├── e09_closure
│ ├── ClosureExamples.java
│ └── ClosureExamples2.java
│ ├── ep10_higher_order_function
│ └── HigherOrderFunctionExamples.java
│ └── ep11_method_reference
│ ├── MethodReferenceExamples.java
│ ├── MethodReferenceExamples2Constructor.java
│ └── MethodReferenceExamples3Array.java
└── test
└── java
└── cc
└── kevinlee
└── modernjava
└── e01
└── CalculatorServiceTest.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target/
2 |
3 | *.pydevproject
4 | .project
5 | .classpath
6 | .settings/
7 | .metadata
8 | bin/
9 | tmp/
10 | *.tmp
11 | *.bak
12 | *.swp
13 | *~.nib
14 | local.properties
15 | .loadpath
16 |
17 | .idea
18 | *.iml
19 |
20 | # External tool builders
21 | .externalToolBuilders/
22 |
23 | # Locally stored "Eclipse launch configurations"
24 | *.launch
25 |
26 | # CDT-specific
27 | .cproject
28 |
29 | # PDT-specific
30 | .buildpath
31 |
32 |
33 | gradle/
34 | gradlew*
35 | .gradle
36 | build/
37 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 모던 자바 (자바8) 못다한 이야기
2 | # Modern Java (Java8) Untold
3 |
4 | 이곳은 제가 유튜브에 올리고 있는 모던 자바 영상에서 작성된 코드를
5 | 정리하고 주석을 달아서 모아 놓은 저장소입니다.
6 |
7 | 앞으로 계속 업데이트 될 예정이니 직접 코드 작성을 하실 경우
8 | clone 하셔서 수정을 하지 마시고, 따로 프로젝트 생성을 하시는게 좋을것 같습니다.
9 | 그렇지 않으면 merge conflict를 경험하시게 될지도...
10 |
11 | **모던 자바 - 못다한 이야기 영상 02~05까지는 볼륨이 좀 작습니다. 죄송합니다. 한번에 다 녹화해서 확인 못했습니다.**
12 |
13 | **중간에 작은 실수한거 수정도 못하고 올려서 5편 이후로는 볼륨 문제를 신경썼고, 7편부터는 녹화한 영상 미리 다 확인하고
14 | 필요한 정보를 추가하거나 삭제하는 편집과정을 도입했습니다.**
15 |
16 | ## 나는 프로그래머다 웨비너
17 |
나는 프로그래머다 웨비너 - 자바8 깊숙히 (무삭제 노모 유출 버전!)
18 |
19 |
20 | ## 모던 자바 - 못다한 이야기
21 |
22 |
모던 자바 (자바8) - 못다한 이야기 영상 - 전편 보기 클릭!
23 | (각편당 링크는 이 밑에 있습니다).
24 |
25 | ### 01. 모던 자바 - 못다한 이야기: 웨비나, 소개, 왜 배워야 하죠?
26 |
27 |
모던 자바 (자바8) - 못다한 이야기: - 00 소개영상
28 |
29 |
모던 자바 (자바8) 못다한 이야기 - 01 왜 배워야 하나요? 뭐가 좋아요?
30 |
31 |
모던 자바 (자바8) 못다한 이야기 - 01-B 왜 배워야 하나요? 뭐가 좋아요? (추가설명편)
32 |
33 | 관련 소스 (클릭!)
34 |
35 |
36 | ### 02. Functional Interface
37 |
모던 자바 (자바8) 못다한 이야기 - 02 Function, The Transformer
38 |
39 | 관련 소스 (클릭!)
40 |
41 |
42 | ### 03. Consumer
43 |
모던 자바 (자바8) 못다한 이야기 - 03 Consumer, The Spartan, "Give Them Nothing but Take from Them Everything" (스파르탄, "모든걸 빼앗고 아무것도 내주지 마라!")
44 |
45 | 관련 소스 (클릭!)
46 |
47 |
48 | ### 04. Predicate
49 |
모던 자바 (자바8) 못다한 이야기 - 04 Predicate, The Judge
50 |
51 | 관련 소스 (클릭!)
52 |
53 |
54 | ### 05. Supplier
55 |
모던 자바 (자바8) 못다한 이야기 - 05 Supplier, The Master of Lazy Evaluation
56 |
57 | 관련 소스 (클릭!)
58 |
59 |
60 | ### 06. 직접 만드는 Functional Interface 어때요? 참 쉽죠?
61 |
모던 자바 (자바8) 못다한 이야기 - 06 직접 만드는 Functional Interface 어때요? 참 쉽죠?
62 |
63 | 관련 소스 (클릭!)
64 |
65 |
66 | ### 07. FunctionalInterface 실전 예제 / 제약 사항
67 |
모던 자바 (자바8) 못다한 이야기 - 07 실전 예제와 Functional Interface의 제약 사항
68 |
69 | 관련 소스 (클릭!)
70 |
71 |
72 | ### 08. Stream API
73 | #### 08 - 01 시작하기전에
74 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 01 시작하기전에
75 |
76 | 관련 소스 (클릭!)
77 |
78 |
79 | #### 08 - 02 Identity Function 예제
80 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 02 Identity Function
81 |
82 | 관련 소스 (클릭!)
83 |
84 |
85 | #### 08 - 03 Stream API - 01 무한 Collection
86 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 03 Stream API 01 - 무한 collection
87 |
88 | 관련 소스 (클릭!)
89 |
90 |
91 | #### 08 - 03 Stream API - 02 Stream vs 예전방식
92 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 03 Stream API 02 - Stream vs 예전방식
93 |
94 | 관련 소스 (클릭!)
95 |
96 |
97 | #### 08 - 03 Stream API - 03 기초
98 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 03 Stream API 03 - 기초
99 |
100 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 03 Stream API 03A - IDE 활용 팁
101 |
102 | 관련 소스 (클릭!)
103 |
104 |
105 | #### 08 - 03 Stream API - 04 좀더 실용적인 예
106 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 03 Stream API 04 - 좀더 실용적인 예
107 |
108 | 관련 소스 (클릭!)
109 |
110 |
111 | #### 08 - 03 Stream API - 05 병렬 프로그래밍 (Parallel Programming with ParallelStream)
112 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 03 Stream API 05 - Parallel Programming (with ParallelStream)
113 |
114 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 03 Stream API 06 - ParallelStream 성능 테스트
115 |
116 | 관련 소스 (클릭!)
117 |
118 |
모던 자바 (자바8) 못다한 이야기 - 08 Stream API - 03 Stream API 07 - ParallelStream 주의 사항과 앞으로의 계획
119 |
120 | JMH: 자바 성능 벤치마크툴 (클릭)
121 |
122 | ### 09. Closure
123 |
124 |
모던 자바 (자바8) 못다한 이야기 - 09 - 01 Closure
125 |
126 | 관련 소스 (클릭!)
127 |
128 |
모던 자바 (자바8) 못다한 이야기 - 09 - 02 Closure 및 Lambda Expression 내부 구현
129 |
130 |
131 | ### 10. Higher-Order Function (HOF, 고차 함수 혹은 고계 함수)
132 |
133 |
모던 자바 (자바8) 못다한 이야기 - 10 - Higher-Order Function
134 |
135 | 관련 소스 (클릭!)
136 |
137 | ### 11. Method Reference (In progress)
138 |
139 |
모던 자바 (자바8) 못다한 이야기 - 11 (1부) - Method Reference
140 |
141 |
모던 자바 (자바8) 못다한 이야기 - 11 (2부) - Method Reference 사용예
142 |
143 |
모던 자바 (자바8) 못다한 이야기 - 11 (3부) - Method Reference로 Method를 Data처럼
144 |
145 |
모던 자바 (자바8) 못다한 이야기 - 11 (4부) Method Reference, Constructor를 Data처럼 사용하기
146 |
147 |
148 | 관련 소스 (클릭!)
149 |
150 | 더 추가될 예정입니다.
151 |
152 |
153 |
--------------------------------------------------------------------------------
/YouTube-social-icon_red_24px.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kevin-lee/modern-java-untold/52e752a37d1d6f5c6425af7da11dcd9a7ba2fad7/YouTube-social-icon_red_24px.png
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | group 'cc.kevinlee'
2 | version '1.0'
3 |
4 | task wrapper(type: Wrapper) {
5 | gradleVersion = '2.5'
6 | distributionUrl = "https://services.gradle.org/distributions/gradle-$gradleVersion-all.zip"
7 | }
8 |
9 | apply plugin: 'java'
10 |
11 | sourceCompatibility = 1.8
12 | targetCompatibility = 1.8
13 |
14 | repositories {
15 | mavenCentral()
16 | maven {
17 | url "http://dl.bintray.com/kevinlee/maven"
18 | }
19 | }
20 |
21 | dependencies {
22 | compile 'cc.kevinlee:j8plus:0.0.15'
23 | compile "org.projectlombok:lombok:1.16.4"
24 |
25 | testCompile 'junit:junit:4.11'
26 | testCompile 'org.assertj:assertj-core:3.0.0'
27 | testCompile 'cc.kevinlee:test0ster1:0.0.6'
28 | }
29 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 | 4.0.0
5 |
6 | cc.kevinlee
7 | modern-java-untold
8 | 1.0
9 | jar
10 |
11 | Modern Java Untold
12 | https://github.com/Kevin-Lee/modern-java-untold
13 |
14 |
15 | UTF-8
16 | 1.8
17 | 4.11
18 | 0.0.6
19 |
20 |
21 |
22 |
23 | kevin-public-releases
24 | Kevin's Public Releases
25 | http://dl.bintray.com/kevinlee/maven
26 |
27 |
28 |
29 |
30 | scm:git:git@kevin-lee-github:Kevin-Lee/modern-java-untold.git
31 | scm:git:git@kevin-lee-github:Kevin-Lee/modern-java-untold.git
32 | https://github.com/Kevin-Lee/modern-java-untold
33 | HEAD
34 |
35 |
36 |
37 |
38 |
39 | org.apache.maven.plugins
40 | maven-compiler-plugin
41 | 3.1
42 |
43 | ${java.version}
44 | ${java.version}
45 | ${project.build.sourceEncoding}
46 |
47 |
48 |
49 | org.apache.maven.plugins
50 | maven-source-plugin
51 | 2.1.2
52 |
53 |
54 | attach-sources
55 |
56 | jar
57 |
58 |
59 |
60 |
61 |
62 | org.apache.maven.plugins
63 | maven-release-plugin
64 | 2.5.1
65 |
66 | true
67 | releases
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 | junit
76 | junit
77 | ${junit.version}
78 | test
79 |
80 |
81 | cc.kevinlee
82 | test0ster1
83 | ${test0ster1.version}
84 | test
85 |
86 |
87 | org.assertj
88 | assertj-core
89 | 3.0.0
90 | test
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | rootProject.name = 'modern-java-untold'
2 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e01/LambdaExample.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e01;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.Comparator;
6 | import java.util.List;
7 | import java.util.concurrent.TimeUnit;
8 | import java.util.function.Predicate;
9 | import java.util.stream.Stream;
10 |
11 | /**
12 | * @author Kevin Lee
13 | * @since 2015-08-01
14 | */
15 | public class LambdaExample {
16 |
17 | public static void main(final String[] args) {
18 |
19 | filteringTest();
20 |
21 | final List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20);
22 |
23 | final int repeat = 5;
24 | System.out.println("\nLambdaExample.raceCondition");
25 | /* 5번 반복 */
26 | Stream.iterate(0, i -> i + 1) // <= 이게 뭐냐구요? 5번 반복인데, 자세한건 Stream API 관련 영상을 기다려주세요!
27 | .limit(repeat)
28 | .forEach(i -> raceCondition(numbers));
29 |
30 | System.out.println("\nLambdaExample.noRaceCondition");
31 | Stream.iterate(0, i -> i + 1) // <= 이게 뭐냐구요? 5번 반복인데, 자세한건 Stream API 관련 영상을 기다려주세요!
32 | .limit(repeat)
33 | .forEach(i -> noRaceCondition(numbers));
34 |
35 | parallelProgramming();
36 | }
37 |
38 | private static void filteringTest() {
39 | System.out.println("\nLambdaExample.filteringTest");
40 | final List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
41 |
42 | /* 예전 방법으로 2보다 큰 정수 찾기 */
43 | final List result = new ArrayList<>(); // boilerplate code
44 | for (final Integer number : list) { // boilerplate code
45 | if (number > 2) { // 이부분만 다름
46 | result.add(number); // boilerplate code
47 | }
48 | }
49 | System.out.println("n > 2 = " + result);
50 |
51 | /* 예전 방법으로 7보다 작은 정수 찾기 */
52 | final List result2 = new ArrayList<>(); // boilerplate code
53 | for (final Integer number : list) { // boilerplate code
54 | if (number < 7) { // 이부분만 다름
55 | result2.add(number); // boilerplate code
56 | }
57 | }
58 | System.out.println("n < 7 = " + result2);
59 |
60 | /* 람다를 이용해서 2보다 큰 정수 찾기 */
61 | final Predicate greaterThan2 = n -> n > 2;
62 | final List result3 = filter(list, greaterThan2);
63 | System.out.println("n > 2 = " + result3);
64 |
65 | /* 람다를 이용해서 7보다 작은 정수 찾기 (기존 filter 메소드 재사용) */
66 | final Predicate lessThan7 = n -> n < 7;
67 | final List result4 = filter(list, lessThan7);
68 | System.out.println("n < 7 = " + result4);
69 |
70 | /* Function composition:
71 | * 2개의 함수를 합쳐서 쉽게
72 | * 2보다 크고 7보다 작은 정수 찾기
73 | */
74 | final List result5 = filter(list, greaterThan2.and(lessThan7));
75 | System.out.println("2 < n < 7 = " + result5);
76 |
77 | /* Closure: 람다 바디에서 람다 바깥에 있는 factor (free variable) 접근
78 | * Note: 엄밀히 따지면 자바의 Closure는 variable이 아니라 거기 들은 값(value)에
79 | * 접근 하는겁니다 (capturing value).
80 | */
81 | int factor = 10; // effectively final
82 | final Comparator comparator = (o1, o2) -> o1 > factor ? o1 : o1.compareTo(o2);
83 |
84 | }
85 |
86 | private static List filter(final List list, final Predicate predicate) {
87 | final List result = new ArrayList<>();
88 | for (final T value : list) {
89 | if (predicate.test(value)) { // predicate의 test를 통과한 경우만 저장
90 | result.add(value);
91 | }
92 | }
93 | return result;
94 | }
95 |
96 |
97 | private static void raceCondition(final List numbers) {
98 |
99 | /* Race condition */
100 | final int[] sum = new int[1];
101 | numbers.parallelStream()
102 | .forEach(i -> sum[0] = sum[0] + i); // mutation!
103 |
104 | System.out.println("race condition: " + sum[0]);
105 | }
106 |
107 | private static void noRaceCondition(final List numbers) {
108 | /* No race condition */
109 | final int total = numbers.parallelStream()
110 | .reduce(0, (i1, i2) -> i1 + i2);
111 | System.out.println("no race condition: " + total);
112 | }
113 |
114 | private static void parallelProgramming() {
115 | System.out.println("\nLambdaExample.parallelProgramming");
116 | final long start = System.currentTimeMillis();
117 | /*
118 | * peek에 넘기는 function은 3초가 걸리는
119 | * 연산을 시뮬레이션한 것입니다.
120 | *
121 | * 코어 4개짜리 CPU에서 3초정도 걸립니다.
122 | * 저장된 숫자를 하나 더 늘리면 (1, 2, 3, 4, 5),
123 | * 처리하는데 8초정도 걸립니다.
124 | *
125 | * 저장된 숫자의 갯수를 CPU코어 만큼 늘려서 테스트 해보시고,
126 | * 코어보다 하나 많게 해서 테스트 해보세요.
127 | * 예) 코어가 8개면
128 | * (1, 2, 3, 4, 5, 6, 7, 8) => 3초정도 걸립니다.
129 | * (1, 2, 3, 4, 5, 6, 7, 8, 9) => 6초정도 걸립니다.
130 | */
131 | final int total = Arrays.asList(1, 2, 3, 4)
132 | .parallelStream()
133 | .peek(i -> {
134 | // 처리 시간 오래 걸리는 함수 시뮬레이션
135 | try {
136 | TimeUnit.SECONDS.sleep(3);
137 | } catch (InterruptedException e) {
138 | e.printStackTrace();
139 | }
140 | })
141 | .reduce(0, (i1, i2) -> i1 + i2);
142 | System.out.println("It took " + ((System.currentTimeMillis() - start) / 1000) + " seconds.");
143 | System.out.println("total: " + total);
144 | }
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e01/OopAndFpExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e01;
2 |
3 | /**
4 | * 이 파일 관련된 내용은 아직 영상 업로드가 안 됐습니다. 이번 주말에 업로드 하면서
5 | * 이 파일도 업데이트 할테니 git pull 해주세요. :)
6 | *
7 | * @author Kevin Lee
8 | * @since 2015-08-02
9 | */
10 | public class OopAndFpExamples {
11 |
12 | public static void main(final String[] args) {
13 | final CalculatorService calculatorService =
14 | new CalculatorService(new Addition(), new Subtraction(), new Multiplication(), new Division());
15 |
16 | final int additionResult = calculatorService.add(11, 4);
17 | System.out.println(additionResult);
18 |
19 | final int subtractionResult = calculatorService.subtract(11, 1);
20 | System.out.println(subtractionResult);
21 |
22 | final int multiplicationResult = calculatorService.multiply(11, 2);
23 | System.out.println(multiplicationResult);
24 |
25 | final int divisionResult = calculatorService.divide(20, 4);
26 | System.out.println(divisionResult);
27 |
28 |
29 | final FpCalculatorService fpCalculatorService = new FpCalculatorService();
30 | final Calculation addition = (i1, i2) -> i1 + i2;
31 | System.out.println(" additon: " + fpCalculatorService.calculate(addition, 11, 4));
32 | System.out.println(" subtraction: " + fpCalculatorService.calculate((i1, i2) -> i1 - i2, 11, 1));
33 | System.out.println("multiplication: " + fpCalculatorService.calculate((i1, i2) -> i1 * i2, 11, 2));
34 | System.out.println(" division: " + fpCalculatorService.calculate((i1, i2) -> i1 / i2, 20, 4));
35 | System.out.println(" custom calc: " + fpCalculatorService.calculate((i1, i2) -> ((i1 + i2) * 2) / i2, 20, 4));
36 | }
37 | }
38 |
39 | interface Calculation {
40 | int calculate(final int num1, final int num2);
41 | }
42 |
43 | class Addition implements Calculation {
44 | @Override
45 | public int calculate(final int num1, final int num2) {
46 | return num1 + num2;
47 | }
48 | }
49 |
50 | class Subtraction implements Calculation {
51 | @Override
52 | public int calculate(final int num1, final int num2) {
53 | return num1 - num2;
54 | }
55 | }
56 |
57 | class Multiplication implements Calculation {
58 | @Override
59 | public int calculate(final int num1, final int num2) {
60 | return num1 * num2;
61 | }
62 | }
63 |
64 | class Division implements Calculation {
65 | @Override
66 | public int calculate(final int num1, final int num2) {
67 | return num1 / num2;
68 | }
69 | }
70 |
71 | class CalculatorService {
72 | private final Calculation addition;
73 | private final Calculation subtraction;
74 | private final Calculation multiplication;
75 | private final Calculation division;
76 |
77 | public CalculatorService(final Calculation addition, final Calculation subtraction, final Calculation multiplication, final Calculation division) {
78 | this.addition = addition;
79 | this.subtraction = subtraction;
80 | this.multiplication = multiplication;
81 | this.division = division;
82 | }
83 |
84 | public int add(final int num1, final int num2) {
85 | if (num1 > 10 && num2 < num1) { // boilerplate code
86 | return addition.calculate(num1, num2);
87 | } else { // boilerplate code
88 | throw new IllegalArgumentException("Invalid input num1: " + num1 + ", num2: " + num2); // boilerplate code
89 | } // boilerplate code
90 | }
91 |
92 | public int subtract(final int num1, final int num2) {
93 | if (num1 > 10 && num2 < num1) { // boilerplate code
94 | return subtraction.calculate(num1, num2);
95 | } else { // boilerplate code
96 | throw new IllegalArgumentException("Invalid input num1: " + num1 + ", num2: " + num2); // boilerplate code
97 | } // boilerplate code
98 | }
99 |
100 | public int multiply(final int num1, final int num2) {
101 | if (num1 > 10 && num2 < num1) { // boilerplate code
102 | return multiplication.calculate(num1, num2);
103 | } else { // boilerplate code
104 | throw new IllegalArgumentException("Invalid input num1: " + num1 + ", num2: " + num2); // boilerplate code
105 | } // boilerplate code
106 | }
107 |
108 | public int divide(final int num1, final int num2) {
109 | if (num1 > 10 && num2 < num1) { // boilerplate code
110 | return division.calculate(num1, num2);
111 | } else { // boilerplate code
112 | throw new IllegalArgumentException("Invalid input num1: " + num1 + ", num2: " + num2); // boilerplate code
113 | } // boilerplate code
114 | }
115 | }
116 |
117 | class FpCalculatorService {
118 | public int calculate(final Calculation calculation, final int num1, final int num2) {
119 | if (num1 > 10 && num2 < num1) {
120 | return calculation.calculate(num1, num2);
121 | } else {
122 | throw new IllegalArgumentException("Invalid input num1: " + num1 + ", num2: " + num2);
123 | }
124 | }
125 | }
126 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e01/OopExample.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e01;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.Collection;
6 | import java.util.HashSet;
7 |
8 | /**
9 | * An example of "Inheritance breaks Encapsulation"
10 | * 상속(Inheritance)이 캡슐화(Encapsulation)를 망치는 예제입니다.
11 | *
12 | * @author Kevin Lee
13 | * @since 2015-08-01
14 | */
15 | public class OopExample {
16 | public static void main(final String[] args) {
17 | final MyList list = new MyList<>();
18 | list.add(1);
19 | list.add(2);
20 | list.add(3);
21 | System.out.println(" list count: " + list.getCount()); // 예상대로 3이 나옵니다.
22 |
23 | final MyList list2 = new MyList<>();
24 | list2.addAll(Arrays.asList(1, 2, 3, 4, 5));
25 | System.out.println(" list2 count: " + list2.getCount()); // 예상대로 5가 나옵니다.
26 |
27 | System.out.println("--------------------");
28 | final MySet mySet = new MySet<>();
29 | mySet.add(1);
30 | mySet.add(2);
31 | mySet.add(3);
32 | System.out.println(" mySet count: " + mySet.getCount()); // 예상대로 3이 나옵니다.
33 |
34 | final MySet mySet2 = new MySet<>();
35 | mySet2.addAll(Arrays.asList(1, 2, 3, 4, 5));
36 | System.out.println(" mySet2 count: " + mySet2.getCount()); // 예상과 달리 10이!!!
37 |
38 | System.out.println("--------------------");
39 | final MyNewSet myNewSet = new MyNewSet<>();
40 | myNewSet.add(1);
41 | myNewSet.add(2);
42 | myNewSet.add(3);
43 | System.out.println(" myNewSet count: " + myNewSet.getCount()); // 예상대로 3이 나옵니다.
44 |
45 | final MyNewSet myNewSet2 = new MyNewSet<>();
46 | myNewSet2.addAll(Arrays.asList(1, 2, 3, 4, 5));
47 | System.out.println("myNewSet2 count: " + myNewSet2.getCount()); // 예상대로 5가 나옵니다.
48 |
49 | }
50 | }
51 |
52 | class MyList extends ArrayList {
53 | private int count;
54 |
55 | public int getCount() {
56 | return count;
57 | }
58 |
59 | @Override
60 | public boolean addAll(final Collection c) {
61 | count += c.size();
62 | return super.addAll(c);
63 | }
64 |
65 | @Override
66 | public boolean add(final E o) {
67 | count++;
68 | return super.add(o);
69 | }
70 | }
71 |
72 |
73 | class MySet extends HashSet {
74 | private int count;
75 |
76 | public int getCount() {
77 | return count;
78 | }
79 |
80 | @Override
81 | public boolean addAll(final Collection c) {
82 | count += c.size();
83 | return super.addAll(c);
84 | }
85 |
86 | @Override
87 | public boolean add(final E o) {
88 | count++;
89 | return super.add(o);
90 | }
91 | }
92 |
93 | /**
94 | * NewSet은 HashSet에 있는 Inheritance가 Encapsulation을 깨뜨리는 것을 미리 예방해서
95 | * 다시 디자인한것입니다. (add 와 addAll 메소드에 한정)
96 | */
97 | class NewSet extends HashSet {
98 | @Override
99 | public boolean add(final E e) {
100 | return add0(e);
101 | }
102 |
103 | private boolean add0(final E e) {
104 | return super.add(e);
105 | }
106 |
107 | @Override
108 | public boolean addAll(final Collection extends E> c) {
109 | boolean modified = false;
110 | for (E e : c)
111 | if (add0(e))
112 | modified = true;
113 | return modified;
114 | }
115 | }
116 |
117 |
118 | class MyNewSet extends NewSet {
119 | private int count;
120 |
121 | public int getCount() {
122 | return count;
123 | }
124 |
125 | @Override
126 | public boolean addAll(final Collection c) {
127 | count += c.size();
128 | return super.addAll(c);
129 | }
130 |
131 | @Override
132 | public boolean add(final E o) {
133 | count++;
134 | return super.add(o);
135 | }
136 | }
137 |
138 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e01/WhyJava8.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e01;
2 |
3 | import java.io.BufferedReader;
4 | import java.io.File;
5 | import java.io.FileReader;
6 | import java.io.IOException;
7 | import java.nio.file.Files;
8 | import java.nio.file.Paths;
9 | import java.util.ArrayList;
10 | import java.util.Arrays;
11 | import java.util.Collections;
12 | import java.util.List;
13 | import java.util.stream.Stream;
14 |
15 | import static java.util.stream.Collectors.joining;
16 | import static java.util.stream.Collectors.toList;
17 |
18 | /**
19 | * @author Kevin Lee
20 | * @since 2015-08-01
21 | */
22 | public class WhyJava8 {
23 | private static final List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
24 |
25 | public static void main(final String[] args) throws IOException {
26 | simpleTask();
27 |
28 | // file 읽기전에 파일을 하나 작성 하셔야 합니다. 파일 위치를 확인해 보세요. 현재는 /tmp/test.txt
29 | readFile();
30 | }
31 |
32 | private static void simpleTask() {
33 |
34 | /* 옛날 옛적 for loop 사용하기 */
35 | final StringBuilder stringBuilder1 = new StringBuilder();
36 | final int size = numbers.size(); // size()매번 호출하면 비효율 적이니까 이렇게... (문제에 집중하기 힘들어요 ㅠ_ㅠ)
37 | for (int i = 0; i < size; i++) { // i에 0 넣고 i가 size 보다 작으면... 가만? 우리가 왜 아직도 이런 코드를 짜야? ㅠ_ㅠ
38 | stringBuilder1.append(numbers.get(i)); // String 빌더에 Integer 추가
39 | if (i != size - 1) { // 현재 index값인 i가 List size 빼기 1 하고 같지 않다? 뭐지? 아! List에 저장된 마지막값!
40 | stringBuilder1.append(" : "); // " : " 추가
41 | }
42 | }
43 |
44 | /* for-each 사용 */
45 | final StringBuilder stringBuilder = new StringBuilder();
46 | final String separator = " : "; // 각 숫자를 연결해줄 " : "
47 | for (final Integer number : numbers) { // 저장된 숫자를 하나씩 받아서
48 | stringBuilder.append(number).append(separator); // String빌더에 숫자 + " : " 추가
49 | }
50 | final int stringLength = stringBuilder.length(); // 빌더 length를 얻고... 근데 왜???
51 | if (stringLength > 0) { // length가 0 보다 크면... 그러니까 왜??? 아!? 뭔가 들어 있으면? isNotEmpty 같은거 없나?
52 | stringBuilder.delete(stringLength - separator.length(), stringLength);
53 | // String빌더 length 빼기 " : ".length부터 String빌더 length까지 지우기? 이게 뭐야?
54 | }
55 | System.out.println(stringBuilder.toString());
56 |
57 | /* Java 8 버전 */
58 | final String result = numbers.stream()
59 | .map(String::valueOf) // 각 Integer를 String으로 변환
60 | .collect(joining(" : ")); // 1 : 2 : 3 : ... 10 끝!
61 | System.out.println(result);
62 | }
63 |
64 | private static void readFile() throws IOException {
65 | /* Java 7 */
66 | try (final FileReader fileReader = new FileReader(new File("/tmp/test.txt"));
67 | final BufferedReader bufferedReader = new BufferedReader(fileReader)) {
68 |
69 | final List uniqueWords = new ArrayList<>(); // 이게 왜 필요하죠?
70 | String line = bufferedReader.readLine(); // 파일 한줄씩 읽기
71 | while (line != null) { // Q: line == null이면 무슨일이? A: EOF
72 | final String[] words = line.split("[\\s]+"); // 공백 문자로 String 나누기
73 | for (final String word : words) {
74 | if (!uniqueWords.contains(word)) { // uniqueWords 안에 word가 없다면?
75 | uniqueWords.add(word); // uniqueWords 안에 word 넣기
76 | }
77 | }
78 | line = bufferedReader.readLine(); // 앗! 깜빡할뻔! 다음 줄 읽기...
79 | }
80 | Collections.sort(uniqueWords); // 오름차순 정렬 (String 기본 정렬)
81 | System.out.println(uniqueWords);
82 | }
83 | // 익셉션을 먹어치운다구요?!
84 | // 절대 집에서 따라하지 마세요. ㅡ_ㅡ;
85 | // catch (final Exception e) { // immutability 를 좋아하는 저는 여기도 final을 씁니다. ;) 이건 따라하면 좋아요. ^^
86 | // }
87 |
88 | /* Java 8 */
89 | try (final Stream lines = Files.lines(Paths.get("/tmp/test.txt"))) {
90 | System.out.println(
91 | lines.map(line -> line.split("[\\s]+")) // String을 공백문자로 나누기
92 | .flatMap(Arrays::stream) // Stream => Stream => Stream 이 귀찮은 2단변신 과정을 한줄로!
93 | .distinct() // 유일한 단어만
94 | .sorted() // 오름차순 정렬 (String 기본 정렬)
95 | .collect(toList())
96 | );
97 | }
98 | }
99 | }
100 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e02_function/FunctionExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e02_function;
2 |
3 | import java.util.function.Function;
4 |
5 | /**
6 | * @author Kevin Lee
7 | * @since 2015-08-01
8 | */
9 | public class FunctionExamples {
10 |
11 | private static void functionExamples() {
12 |
13 | final Function toInt = value -> Integer.parseInt(value);
14 |
15 | final Integer number = toInt.apply("100");
16 | System.out.println(number);
17 |
18 | final Function identity = Function.identity();
19 | final Function identity2 = t -> t;
20 |
21 | System.out.println(identity.apply(999));
22 | System.out.println(identity2.apply(999));
23 | }
24 |
25 |
26 | public static void main(final String[] args) {
27 | functionExamples();
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e03_consumer/ConsumerExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e03_consumer;
2 |
3 | import java.util.function.Consumer;
4 |
5 | /**
6 | * @author Kevin Lee
7 | * @since 2015-08-01
8 | */
9 | public class ConsumerExamples {
10 |
11 | private static void consumerExamples() {
12 |
13 | final Consumer print = value -> System.out.println(value);
14 | print.accept("Hello");
15 |
16 | final Consumer greetings = value -> System.out.println("Hello " + value);
17 | greetings.accept("World");
18 | greetings.accept("Kevin");
19 |
20 | }
21 |
22 | public static void main(final String[] args) {
23 | consumerExamples();
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e04_predicate/PredicateExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e04_predicate;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.function.Predicate;
7 |
8 | /**
9 | * @author Kevin Lee
10 | * @since 2015-08-01
11 | */
12 | public class PredicateExamples {
13 |
14 | private static void predicateExamples() {
15 |
16 | final Predicate isPositive = i -> i > 0;
17 |
18 | System.out.println(isPositive.test(1));
19 | System.out.println(isPositive.test(0));
20 | System.out.println(isPositive.test(-1));
21 |
22 | final List numbers = Arrays.asList(-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5);
23 |
24 | final List positiveNumbers = new ArrayList<>();
25 | for (final Integer num : numbers) {
26 | if (isPositive.test(num)) {
27 | positiveNumbers.add(num);
28 | }
29 | }
30 | System.out.println("positive integers: " + positiveNumbers);
31 |
32 | final Predicate lessThan3 = i -> i < 3;
33 | final List numbersLessThan3 = new ArrayList<>();
34 | for (final Integer num : numbers) {
35 | if (lessThan3.test(num)) {
36 | numbersLessThan3.add(num);
37 | }
38 | }
39 | System.out.println("less than 3: " + numbersLessThan3);
40 |
41 | System.out.println("positive integers: " + filter(numbers, isPositive));
42 | System.out.println("less than 3: " + filter(numbers, lessThan3));
43 |
44 | }
45 |
46 | private static List filter(final List list, final Predicate filter) {
47 | final List result = new ArrayList<>();
48 | for (final T input : list) {
49 | if (filter.test(input)) {
50 | result.add(input);
51 | }
52 | }
53 | return result;
54 | }
55 |
56 | public static void main(final String[] args) {
57 | predicateExamples();
58 | }
59 |
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e05_supplier/SupplierExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e05_supplier;
2 |
3 | import java.util.concurrent.TimeUnit;
4 | import java.util.function.Supplier;
5 |
6 | /**
7 | * @author Kevin Lee
8 | * @since 2015-08-01
9 | */
10 | public class SupplierExamples {
11 |
12 | /**
13 | * 계산 하는데 오래 걸리는 메소드를 시뮬레이션 해봤습니다. 항상 3초가 걸려요.
14 | *
15 | * @return 항상 "Kevin"만 리턴
16 | */
17 | private static String getVeryExpensiveValue() {
18 | try {
19 | TimeUnit.SECONDS.sleep(3);
20 | } catch (InterruptedException e) {
21 | e.printStackTrace();
22 | }
23 | return "Kevin";
24 | }
25 |
26 | private static void callingExpensiveMethodWithoutSupplier() {
27 | System.out.println("SupplierExamples.callingExpensiveMethodWithoutSupplier()");
28 | final long start = System.currentTimeMillis();
29 | printIfValidIndex(0, getVeryExpensiveValue());
30 | printIfValidIndex(-1, getVeryExpensiveValue());
31 | printIfValidIndex(-2, getVeryExpensiveValue());
32 | System.out.println("It took " + ((System.currentTimeMillis() - start) / 1000) + " seconds.");
33 |
34 | }
35 |
36 | private static void printIfValidIndex(final int number, final String value) {
37 | if (number >= 0) {
38 | System.out.println("The value is " + value + ".");
39 | } else {
40 | System.out.println("Invalid");
41 | }
42 | }
43 |
44 | private static void callingExpensiveMethodWithSupplier() {
45 | System.out.println("SupplierExamples.callingExpensiveMethodWithSupplier()");
46 | final long start = System.currentTimeMillis();
47 | printIfValidIndex(0, () -> getVeryExpensiveValue());
48 | printIfValidIndex(-1, () -> getVeryExpensiveValue());
49 | printIfValidIndex(-2, () -> getVeryExpensiveValue());
50 | System.out.println("It took " + ((System.currentTimeMillis() - start) / 1000) + " seconds.");
51 | }
52 |
53 |
54 | private static void printIfValidIndex(final int number, final Supplier valueSupplier) {
55 | if (number >= 0) {
56 | System.out.println("The value is " + valueSupplier.get() + ".");
57 | } else {
58 | System.out.println("Invalid");
59 | }
60 | }
61 |
62 |
63 | private static void supplierExamples() {
64 | System.out.println("SupplierExamples.supplierExamples()");
65 | final Supplier helloSupplier = () -> "Hello ";
66 | System.out.println(helloSupplier.get() + "world");
67 | }
68 |
69 |
70 | public static void main(final String[] args) {
71 | supplierExamples();
72 |
73 | System.out.println("\nSupplier 사용하지 않고 시간 오래 걸리는 메소드 호출");
74 | callingExpensiveMethodWithoutSupplier();
75 |
76 | System.out.println("\nSupplier 사용해서 시간 오래 걸리는 메소드 호출");
77 | callingExpensiveMethodWithSupplier();
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e06_custom_functionalinterface/CustomFunctionalInterfaceExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e06_custom_functionalinterface;
2 |
3 | import java.math.BigDecimal;
4 |
5 | /**
6 | * @author Kevin Lee
7 | * @since 2015-08-01
8 | */
9 | public class CustomFunctionalInterfaceExamples {
10 |
11 | public static void main(final String[] args) {
12 | println(1, 2, 3,
13 | (i1, i2, i3) -> String.valueOf(i1 + i2 + i3));
14 | println("Area is ", 12, 20,
15 | (message, length, width) -> message + (length * width));
16 | println(1L, "Kevin", "test@email.com",
17 | (id, name, email) -> "User info: ID=" + id + ", name=" + name + ", email=" + email);
18 |
19 | final Function3 f3 = (i1, i2, i3) -> String.valueOf(i1 + i2 + i3);
20 |
21 | final BigDecimalToCurrency bigDecimalToCurrency = bd -> "$" + bd.toString();
22 | System.out.println(bigDecimalToCurrency.toCurrency(new BigDecimal("120.00")));
23 |
24 | final InvalidFunctionalInterface anonymousClass = new InvalidFunctionalInterface() {
25 | @Override
26 | public String mkString(final T value) {
27 | return value.toString();
28 | }
29 | };
30 | System.out.println("anonymous class: " + anonymousClass.mkString(123));
31 |
32 | // value -> value.toString() 부분에서 에러! Target method is generic.
33 | // final InvalidFunctionalInterface invalidFunctionalInterface = value -> value.toString();
34 | // System.out.println(invalidFunctionalInterface.mkString(123));
35 | }
36 |
37 | private static void println(T1 t1, T2 t2, T3 t3, Function3 function) {
38 | System.out.println(function.apply(t1, t2, t3));
39 | }
40 | }
41 |
42 | @FunctionalInterface
43 | interface Function3 {
44 | R apply(T1 t1, T2 t2, T3 t3);
45 |
46 | // void print(int i);
47 | }
48 |
49 | @FunctionalInterface
50 | interface BigDecimalToCurrency {
51 | String toCurrency(BigDecimal value);
52 | }
53 |
54 | /**
55 | * Generic method를 가지는 FunctionalInterface는
56 | * Lambda Expression을 사용할수 없습니다.
57 | */
58 | @FunctionalInterface
59 | interface InvalidFunctionalInterface {
60 | String mkString(T value);
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e07_functionalinterface_examples/FunctionalInterfaceExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e07_functionalinterface_examples;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 | import lombok.ToString;
6 |
7 | import java.math.BigDecimal;
8 | import java.util.ArrayList;
9 | import java.util.Arrays;
10 | import java.util.List;
11 | import java.util.function.Function;
12 | import java.util.function.Predicate;
13 |
14 | /**
15 | * @author Kevin Lee
16 | * @since 2015-08-08
17 | */
18 | public class FunctionalInterfaceExamples {
19 | public static void main(String[] args) {
20 | final Product productA = new Product(1L, "A", new BigDecimal("10.00"));
21 | final Product productB = new Product(2L, "B", new BigDecimal("55.50"));
22 | final Product productC = new Product(3L, "C", new BigDecimal("17.45"));
23 | final Product productD = new Product(4L, "D", new BigDecimal("20.00"));
24 | final Product productE = new Product(5L, "E", new BigDecimal("110.99"));
25 | final List products = Arrays.asList(productA, productB, productC, productD, productE);
26 |
27 | final BigDecimal twenty = new BigDecimal("20");
28 | /* 가격이 $20 이상 되는 Product 찾기 */
29 | System.out.println("products >= $20: " +
30 | filter(products, product -> product.getPrice().compareTo(twenty) >= 0)
31 | );
32 | /* 가격이 $10 이하 되는 Product 찾기 */
33 | System.out.println("products <= $10: " +
34 | filter(products, product -> product.getPrice().compareTo(new BigDecimal("10")) <= 0)
35 | );
36 |
37 | /* 가격이 $50 초과되는 Product 찾기 */
38 | final List expensiveProducts =
39 | filter(products, product -> product.getPrice().compareTo(new BigDecimal("50")) > 0);
40 |
41 | /*
42 | * 가격이 $50 초과되는 Product를 찾은후 (filter)
43 | * 50% 할인 가격 적용 (원래 가격 * 0.5)
44 | */
45 | final List discountedProducts =
46 | map(
47 | filter(products, product -> product.getPrice().compareTo(new BigDecimal("50")) > 0),
48 | product -> new DiscountedProduct(product.getId(),
49 | product.getName(),
50 | product.getPrice().multiply(new BigDecimal("0.5")))
51 | );
52 |
53 | System.out.println(" expensive products: " + expensiveProducts);
54 | System.out.println("discounted products: " + discountedProducts);
55 |
56 | final Predicate lessThanOrEqualTo30 =
57 | product -> product.getPrice().compareTo(new BigDecimal("30")) <= 0;
58 | System.out.println("discounted products (<= $30)" +
59 | filter(discountedProducts, lessThanOrEqualTo30)
60 | );
61 | System.out.println(" products (<= $30)" +
62 | filter(products, lessThanOrEqualTo30)
63 | );
64 |
65 | final List prices = map(products, product -> product.getPrice());
66 | BigDecimal total = BigDecimal.ZERO;
67 | for (final BigDecimal price : prices) {
68 | total = total.add(price);
69 | }
70 | System.out.println(" total: " + total);
71 |
72 | final BigDecimal newTotal = total(products, product -> product.getPrice());
73 | System.out.println("newTotal: " + newTotal);
74 |
75 | final BigDecimal discountedTotal = total(discountedProducts, product -> product.getPrice());
76 | System.out.println("discountedTotal: " + discountedTotal);
77 |
78 |
79 | final Order order = new Order(1L, "on-1234", Arrays.asList(
80 | new OrderedItem(1L, productA, 2),
81 | new OrderedItem(2L, productC, 1),
82 | new OrderedItem(3L, productD, 10)
83 | ));
84 |
85 | BigDecimal orderTotal = BigDecimal.ZERO;
86 | for (OrderedItem item : order.getItems()) {
87 | orderTotal =
88 | /* price * quantity = OrderedItem 가격합계 */
89 | orderTotal.add(
90 | item.getProduct().getPrice().multiply(new BigDecimal(item.getQuantity()))
91 | );
92 | }
93 | System.out.println("order total in old way: " + orderTotal);
94 | System.out.println(" order total: " + order.totalPrice());
95 |
96 | }
97 |
98 | private static List filter(final List list, final Predicate super T> predicate) {
99 | final List result = new ArrayList<>();
100 | for (final T t : list) {
101 | if (predicate.test(t)) {
102 | /* Predicate.test()를 만족하는 경우만 저장 */
103 | result.add(t);
104 | }
105 | }
106 | return result;
107 | }
108 |
109 | private static List map(final List list, final Function function) {
110 | final List result = new ArrayList<>();
111 | for (final T t : list) {
112 | /* function을 이용해서 타입변환: T -> R */
113 | result.add(function.apply(t));
114 | }
115 | return result;
116 | }
117 |
118 | private static BigDecimal total(final List list, final Function mapper) {
119 | BigDecimal total = BigDecimal.ZERO;
120 | for (final T t : list) {
121 | /* mapper를 이용해서 T타입을 BigDecimal로 변환 */
122 | total = total.add(mapper.apply(t));
123 | }
124 | return total;
125 | }
126 |
127 | /* 이 아래에 있는 JavaBean들은 Lombok을 사용하셔야 합니다. 영상을 참조해 주세요. */
128 |
129 | @AllArgsConstructor
130 | @Data
131 | static class Product {
132 | private Long id;
133 | private String name;
134 | private BigDecimal price;
135 | }
136 |
137 | @ToString(callSuper = true)
138 | static class DiscountedProduct extends Product {
139 | public DiscountedProduct(final Long id, final String name, final BigDecimal price) {
140 | super(id, name, price);
141 | }
142 | }
143 |
144 | @AllArgsConstructor
145 | @Data
146 | static class OrderedItem {
147 | private Long id;
148 | private Product product;
149 | private int quantity;
150 |
151 | public BigDecimal getItemTotal() {
152 | return product.getPrice().multiply(new BigDecimal(quantity));
153 | }
154 | }
155 |
156 | @AllArgsConstructor
157 | @Data
158 | static class Order {
159 | private Long id;
160 | private String orderNumber;
161 | private List items;
162 |
163 | public BigDecimal totalPrice() {
164 | return total(items, item -> item.getItemTotal());
165 | }
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e08_01_stream_prelude/StreamPrelude.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e08_01_stream_prelude;
2 |
3 | /**
4 | * @author Kevin Lee
5 | * @since 2015-08-15
6 | */
7 | public class StreamPrelude {
8 | public static void main(String[] args) {
9 | /**
10 | * 다른 입력값, 같은 결과값
11 | * 입력: -1, 1
12 | * 결과: 1
13 | */
14 | final int abs1 = Math.abs(-1);
15 | final int abs2 = Math.abs(1);
16 |
17 | System.out.println("abs1: " + abs1);
18 | System.out.println("abs2: " + abs2);
19 | System.out.println("abs1 == abs2 is " + (abs1 == abs2));
20 |
21 | /**
22 | * 입력값: -2147483648
23 | * 결과값: -2147483648
24 | * WARNING!: 사용하실때 주의하세요!
25 | */
26 | System.out.println(Integer.MIN_VALUE);
27 | System.out.println(Integer.MAX_VALUE);
28 | final int minInt = Math.abs(Integer.MIN_VALUE);
29 | System.out.println("minInt: " + minInt);
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e08_02_identity/IdentityExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e08_02_identity;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.function.Function;
7 |
8 | /**
9 | * @author Kevin Lee
10 | * @since 2015-08-15
11 | */
12 | public class IdentityExamples {
13 | public static void main(String[] args) {
14 |
15 | final List numbers = Arrays.asList(1, 2, 3, 4, 5);
16 | System.out.println("\nmapOld(numbers, i -> i * 2)");
17 | System.out.println(
18 | mapOld(numbers, i -> i * 2)
19 | );
20 |
21 | System.out.println("mapOld(numbers, null)");
22 | System.out.println(
23 | mapOld(numbers, null)
24 | );
25 |
26 | System.out.println("");
27 | System.out.println("map(numbers, i -> i * 2)\n" +
28 | map(numbers, i -> i * 2)
29 | );
30 | System.out.println("map(numbers, i -> i)\n" +
31 | map(numbers, i -> i)
32 | );
33 | System.out.println("map(numbers, Function.identity())\n" +
34 | map(numbers, Function.identity())
35 | );
36 | }
37 |
38 | private static List map(final List list, final Function mapper) {
39 | final List result = new ArrayList<>();
40 | for (final T t : list) {
41 | result.add(mapper.apply(t));
42 | }
43 | return result;
44 | }
45 |
46 | private static List mapOld(final List list, final Function mapper) {
47 | final List result;
48 | if (mapper != null) {
49 | result = new ArrayList<>();
50 | } else {
51 | result = new ArrayList<>((List) list);
52 | }
53 | if (result.isEmpty()) {
54 | for (final T t : list) {
55 | result.add(mapper.apply(t));
56 | }
57 | }
58 | return result;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e08_03_stream_01/StreamExamples1.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e08_03_stream_01;
2 |
3 | import java.math.BigInteger;
4 | import java.util.stream.IntStream;
5 | import java.util.stream.Stream;
6 |
7 | /**
8 | * @author Kevin Lee
9 | * @since 2015-08-15
10 | */
11 | public class StreamExamples1 {
12 | public static void main(String[] args) {
13 |
14 | range();
15 | /**
16 | * 아래 두 메소드를 실행하고 그냥 두시면 숫자가 계속 증가합니다.
17 | * 꼭 강제종료 시켜주세요.
18 | */
19 | // infiniteCollection1();
20 | // infiniteCollection2();
21 | }
22 |
23 | private static void range() {
24 | /**
25 | * 0 1 2 3 4 5 6 7 8 9
26 | */
27 | IntStream.range(0, 10)
28 | .forEach(i -> System.out.print(i + " "));
29 |
30 | /**
31 | * 1 2 3 4 5 6 7 8 9 10
32 | */
33 | IntStream.rangeClosed(1, 10)
34 | .forEach(i -> System.out.print(i + " "));
35 | }
36 |
37 | /**
38 | * int를 이용한 무한 Collection
39 | */
40 | private static void infiniteCollection1() {
41 | IntStream.iterate(1, i -> i + 1)
42 | .forEach(i -> System.out.print(i + " "));
43 | }
44 |
45 | /**
46 | * BigInteger를 이용한 무한 Collection
47 | */
48 | private static void infiniteCollection2() {
49 | Stream.iterate(BigInteger.ONE, i -> i.add(BigInteger.ONE))
50 | .forEach(i -> System.out.print(i + " "));
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e08_03_stream_02/StreamExamples2.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e08_03_stream_02;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.concurrent.atomic.AtomicInteger;
7 | import java.util.function.Function;
8 | import java.util.function.Predicate;
9 | import java.util.stream.Stream;
10 |
11 | /**
12 | * @author Kevin Lee
13 | * @since 2015-08-16
14 | */
15 | public class StreamExamples2 {
16 | private static final List NUMBERS = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
17 |
18 | public static void main(String[] args) {
19 | Stream.of(1, 2, 3, 4, 5)
20 | .forEach(i -> System.out.print(i + " "));
21 | System.out.println("\n==================================");
22 |
23 | Integer result = null;
24 | for (final Integer number : NUMBERS) {
25 | if (number > 3 && number < 9) {
26 | final Integer newNumber = number * 2;
27 | if (newNumber > 10) {
28 | result = newNumber;
29 | break;
30 | }
31 | }
32 | }
33 | System.out.println("\n==================================");
34 | System.out.println("Imperative Result: " + result);
35 |
36 |
37 | System.out.println("\n==================================");
38 | System.out.println("Functional Result: " +
39 | NUMBERS.stream()
40 | .filter(number -> number > 3)
41 | .filter(number -> number < 9)
42 | .map(number -> number * 2)
43 | .filter(number -> number > 10)
44 | .findFirst()
45 | );
46 |
47 | System.out.println("\n==================================");
48 | System.out.println("Functional Result (with logging): " +
49 | NUMBERS.stream()
50 | .filter(number -> {
51 | System.out.println("number > 3");
52 | return number > 3;
53 | })
54 | .filter(number -> {
55 | System.out.println("number < 9");
56 | return number < 9;
57 | })
58 | .map(number -> {
59 | System.out.println("number * 2");
60 | return number * 2;
61 | })
62 | .filter(number -> {
63 | System.out.println("number > 10");
64 | return number > 10;
65 | })
66 | .findFirst()
67 | );
68 | System.out.println("\n==================================");
69 |
70 | final List greaterThan3 = filter(NUMBERS, i -> i > 3);
71 | final List lessThan9 = filter(greaterThan3, i -> i < 9);
72 | final List doubled = map(lessThan9, i -> i * 2);
73 | final List greaterThan10 = filter(doubled, i -> i > 10);
74 | System.out.println("My own method result: " + greaterThan10);
75 | System.out.println("My own method result.get(0): " + greaterThan10.get(0));
76 |
77 | System.out.println("\n==================================");
78 | final List myOwnMethodResult =
79 | filter(
80 | map(
81 | filter(
82 | filter(NUMBERS,
83 | i -> i > 3),
84 | i -> i < 9),
85 | i -> i * 2),
86 | i -> i > 10);
87 | System.out.println("My own method result: " + myOwnMethodResult);
88 | System.out.println("My own method result.get(0): " + myOwnMethodResult.get(0));
89 |
90 | System.out.println("\n==================================");
91 | customMethodsWithLogging();
92 | }
93 |
94 | private static void customMethodsWithLogging() {
95 | final AtomicInteger count = new AtomicInteger(1);
96 |
97 | final List greaterThan3 = filter(NUMBERS, i -> {
98 | System.out.println(count.getAndAdd(1) + ": i > 3");
99 | return i > 3;
100 | });
101 | final List lessThan9 = filter(greaterThan3, i -> {
102 | System.out.println(count.getAndAdd(1) + ": i < 9");
103 | return i < 9;
104 | });
105 | final List doubled = map(lessThan9, i -> {
106 | System.out.println(count.getAndAdd(1) + ": i * 2");
107 | return i * 2;
108 | });
109 | final List greaterThan10 = filter(doubled, i -> {
110 | System.out.println(count.getAndAdd(1) + ": i > 10");
111 | return i > 10;
112 | });
113 | System.out.println("My own method result: " + greaterThan10);
114 | System.out.println("My own method result.get(0): " + greaterThan10.get(0));
115 | }
116 |
117 | private static List filter(List list, Predicate super T> predicate) {
118 | final List result = new ArrayList<>();
119 | for (final T t : list) {
120 | if (predicate.test(t)) {
121 | result.add(t);
122 | }
123 | }
124 | return result;
125 | }
126 |
127 | private static List map(List list, Function mapper) {
128 | final List result = new ArrayList<>();
129 | for (final T t : list) {
130 | result.add(mapper.apply(t));
131 | }
132 | return result;
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e08_03_stream_03/StreamExamples3.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e08_03_stream_03;
2 |
3 | import java.util.Arrays;
4 | import java.util.List;
5 | import java.util.stream.Stream;
6 |
7 | import static java.util.stream.Collectors.*;
8 |
9 | /**
10 | * @author Kevin Lee
11 | * @since 2015-08-22
12 | */
13 | public class StreamExamples3 {
14 | public static void main(String[] args) {
15 | System.out.println("collect(toList()): " +
16 | Stream.of(1, 3, 3, 5, 5)
17 | .filter(i -> i > 2)
18 | .map(i -> i * 2)
19 | .map(i -> "#" + i)
20 | .collect(toList())
21 | );
22 |
23 | System.out.println("collect(toSet()): " +
24 | Stream.of(1, 3, 3, 5, 5)
25 | .filter(i -> i > 2)
26 | .map(i -> i * 2)
27 | .map(i -> "#" + i)
28 | .collect(toSet())
29 | );
30 |
31 | System.out.println("collect(joining()): " +
32 | Stream.of(1, 3, 3, 5, 5)
33 | .filter(i -> i > 2)
34 | .map(i -> i * 2)
35 | .map(i -> "#" + i)
36 | .collect(joining())
37 | );
38 |
39 | System.out.println("collect(joining(\", \")): " +
40 | Stream.of(1, 3, 3, 5, 5)
41 | .filter(i -> i > 2)
42 | .map(i -> i * 2)
43 | .map(i -> "#" + i)
44 | .collect(joining(", "))
45 | );
46 |
47 | System.out.println("collect(joining(\", \", \"[\", \"]\")): " +
48 | Stream.of(1, 3, 3, 5, 5)
49 | .filter(i -> i > 2)
50 | .map(i -> i * 2)
51 | .map(i -> "#" + i)
52 | .collect(joining(", ", "[", "]")) // [#6, #6, #10, #10]
53 | );
54 |
55 | System.out.println("distinct().collect(joining(\", \", \"[\", \"]\")): " +
56 | Stream.of(1, 3, 3, 5, 5)
57 | .filter(i -> i > 2)
58 | .map(i -> i * 2)
59 | .map(i -> "#" + i)
60 | .distinct()
61 | .collect(joining(", ", "[", "]"))
62 | );
63 |
64 | System.out.println("distinct().collect(toList()): " +
65 | Stream.of(1, 3, 3, 5, 5)
66 | .filter(i -> i > 2)
67 | .map(i -> i * 2)
68 | .map(i -> "#" + i)
69 | .distinct()
70 | .collect(toList())
71 | );
72 |
73 | final Integer integer3 = 3;
74 | System.out.println(
75 | Stream.of(1, 2, 3, 4, 5)
76 | .filter(i -> i == integer3)
77 | .findFirst()
78 | );
79 |
80 | final Integer integer127 = 127;
81 | System.out.println(
82 | Stream.of(1, 2, 3, 4, 5, 127)
83 | .filter(i -> i == integer127)
84 | .findFirst()
85 | );
86 |
87 | final Integer integer128 = 128;
88 | System.out.println(
89 | Stream.of(1, 2, 3, 4, 5, 128)
90 | .filter(i -> i == integer128)
91 | .findFirst()
92 | );
93 |
94 |
95 | System.out.println(
96 | Stream.of(1, 2, 3, 4, 5, 128)
97 | .filter(i -> i.equals(integer128))
98 | .findFirst()
99 | );
100 |
101 | System.out.println(".filter(i -> i > integer3).count(): " +
102 | Stream.of(1, 2, 3, 4, 5)
103 | .filter(i -> i > integer3)
104 | .count()
105 | );
106 |
107 | final List numbers = Arrays.asList(1, 2, 3, 4, 5);
108 | System.out.println("for (Integer i : numbers): ");
109 | for (Integer i : numbers) {
110 | System.out.print("i = " + i + " ");
111 | }
112 |
113 | System.out.println("\n\nforEach(i -> System.out.println(i)): ");
114 | Stream.of(1, 2, 3, 4, 5)
115 | .forEach(i -> System.out.print(i + " "));
116 |
117 | }
118 | }
119 |
120 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e08_03_stream_04/StreamExamples4.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e08_03_stream_04;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 |
6 | import java.math.BigDecimal;
7 | import java.util.Arrays;
8 | import java.util.List;
9 | import java.util.stream.IntStream;
10 |
11 | import static java.util.stream.Collectors.*;
12 |
13 | /**
14 | * @author Kevin Lee
15 | * @since 2015-08-22
16 | */
17 | public class StreamExamples4 {
18 | public static void main(String[] args) {
19 | final List products =
20 | Arrays.asList(
21 | new Product(1L, "A", new BigDecimal("100.50")),
22 | new Product(2L, "B", new BigDecimal("23.00")),
23 | new Product(3L, "C", new BigDecimal("31.45")),
24 | new Product(4L, "D", new BigDecimal("80.20")),
25 | new Product(5L, "E", new BigDecimal("7.50"))
26 | );
27 |
28 | System.out.println("Products.price >= 30: \n" +
29 | products.stream()
30 | .filter(product -> product.getPrice().compareTo(new BigDecimal("30")) >= 0)
31 | .collect(toList())
32 | );
33 | System.out.println("\n==================================");
34 | System.out.println("Products.price >= 30 (with joining(\"\\n\")): \n" +
35 | products.stream()
36 | .filter(product -> product.getPrice().compareTo(new BigDecimal("30")) >= 0)
37 | .map(product -> product.toString())
38 | .collect(joining("\n"))
39 | );
40 |
41 | System.out.println("\n===========================");
42 | System.out.println("IntStream.sum: " +
43 | IntStream.of(1, 2, 3, 4, 5)
44 | .sum()
45 | );
46 |
47 | System.out.println("\n===========================");
48 | System.out.println("Total Price: " +
49 | products.stream()
50 | .map(product -> product.getPrice())
51 | .reduce(BigDecimal.ZERO, (price1, price2) -> price1.add(price2))
52 | );
53 |
54 | System.out.println("\n===========================");
55 | System.out.println("Total price (where Product.price >= 30): " +
56 | products.stream()
57 | .filter(product -> product.getPrice().compareTo(new BigDecimal("30")) >= 0)
58 | .map(product -> product.getPrice())
59 | .reduce(BigDecimal.ZERO, (price1, price2) -> price1.add(price2))
60 | );
61 |
62 | System.out.println("\n===========================");
63 | /*
64 | * BigDecimal타입과 Product타입을 동시에 사용하는 방법입니다만,
65 | * 불필요한 코드가 늘고 가독성이 떨어지기 때문에 권장하지 않습니다
66 | */
67 | System.out.println("Total price (where Product.price >= 30) (not recommended): " +
68 | products.stream()
69 | .filter(product -> product.getPrice().compareTo(new BigDecimal("30")) >= 0)
70 | .reduce(BigDecimal.ZERO,
71 | (price, product) -> price.add(product.getPrice()), // (BigDecimal, Product) -> BigDecimal
72 | (price1, price2) -> price1.add(price2)) // (BigDecimal, BigDecimal) -> BigDecimal
73 | );
74 |
75 | System.out.println("\n===========================");
76 | System.out.println("The number of Products (where Product.price >= 30): " +
77 | products.stream()
78 | .filter(product -> product.getPrice().compareTo(new BigDecimal("30")) >= 0)
79 | .count()
80 | );
81 |
82 | final OrderedItem item1 = new OrderedItem(1L, products.get(0), 1);
83 | final OrderedItem item2 = new OrderedItem(2L, products.get(2), 3);
84 | final OrderedItem item3 = new OrderedItem(3L, products.get(4), 10);
85 |
86 | final Order order = new Order(1L, Arrays.asList(item1, item2, item3));
87 |
88 | System.out.println("\n===========================");
89 | System.out.println("order.totalPrice(): " + order.totalPrice());
90 | }
91 | }
92 |
93 | @AllArgsConstructor
94 | @Data
95 | class Product {
96 | private Long id;
97 | private String name;
98 | private BigDecimal price;
99 | }
100 |
101 | @AllArgsConstructor
102 | @Data
103 | class OrderedItem {
104 | private Long id;
105 | private Product product;
106 | private int quantity;
107 |
108 | public BigDecimal getTotalPrice() {
109 | return product.getPrice().multiply(new BigDecimal(quantity));
110 | }
111 | }
112 |
113 | @AllArgsConstructor
114 | @Data
115 | class Order {
116 | private Long id;
117 | private List items;
118 |
119 | public BigDecimal totalPrice() {
120 | return items.stream()
121 | .map(item -> item.getTotalPrice())
122 | .reduce(BigDecimal.ZERO, (price1, price2) -> price1.add(price2));
123 | }
124 | }
125 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e08_03_stream_05_parallel/StreamExamples5Parallel.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e08_03_stream_05_parallel;
2 |
3 | import java.util.List;
4 | import java.util.concurrent.TimeUnit;
5 | import java.util.stream.IntStream;
6 |
7 | import static java.util.stream.Collectors.*;
8 |
9 | /**
10 | * @author Kevin Lee
11 | * @since 2015-08-23
12 | */
13 | public class StreamExamples5Parallel {
14 |
15 |
16 | public static void main(String[] args) {
17 |
18 | raceConditionTest();
19 |
20 | /*
21 | * 사용중인 컴퓨터의 코어 개수를 찾는 코드입니다.
22 | */
23 | int numOfCores = Runtime.getRuntime().availableProcessors();
24 |
25 | streamTest(numOfCores);
26 |
27 | parallelStreamTest(numOfCores);
28 | parallelStreamTest(numOfCores + 1);
29 |
30 | /**
31 | * System.setProperty로 parallelism을 설정할 경우 몇 가지 문제가 있을 수 있습니다.
32 | * 1. JVM레벨 설정이므로 예기치 못한곳에서 원치 않는 코어 사용/비사용 문제가 발생할수 있습니다.
33 | * 2. System.setProperty로 parallelism을 설정하기 전에 Parallel Stream 을 사용할 경우
34 | * setProperty로 설정한 값의 영향을 받지 않는것을 확인 했습니다. 아무래도 이미 생성된 ForkJoinPool을 내부적으로
35 | * 그대로 사용하기 때문인것 같습니다.
36 | * 3. 결국 JVM 실행시 옵션으로 설정하시는것을 권장합니다.
37 | * e.g.) java -D java.util.concurrent.ForkJoinPool.common.parallelism=3 some.package.MainClassName
38 | */
39 | // System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", String.valueOf(numOfCores - 1));
40 | parallelStreamTest(numOfCores);
41 | }
42 |
43 |
44 | /**
45 | * Race Condition을 보여주는 코드입니다.
46 | * Parallel Programming을 할경우 side-effect, 이 예제의 경우, variable의 값을
47 | * 계속 re-assign하는 방법을 이용하게 되면 Race Condition이 발생하기 쉽습니다.
48 | */
49 | private static void raceConditionTest() {
50 | System.out.println("\n=========================================");
51 | System.out.println("StreamExamples5Parallel.raceConditionTest");
52 |
53 | final int[] sum = {0};
54 | IntStream.range(0, 100)
55 | .forEach(i -> sum[0] += i);
56 |
57 | System.out.println(" stream sum (side-effect): " + sum[0]);
58 | final int[] sum2 = {0};
59 | IntStream.range(0, 100)
60 | .parallel()
61 | .forEach(i -> sum2[0] += i);
62 |
63 | System.out.println(" parallel sum (side-effect): " + sum2[0]);
64 |
65 | System.out.println(" stream sum (no side-effect): " +
66 | IntStream.range(0, 100)
67 | .sum());
68 |
69 | System.out.println("parallel stream sum (no side-effect): " +
70 | IntStream.range(0, 100)
71 | .parallel()
72 | .sum());
73 | }
74 |
75 |
76 | private static void streamTest(int numOfCores) {
77 |
78 | System.out.println("\n==================================");
79 | System.out.println("StreamExamples5Parallel.streamTest");
80 | final List numbers = getNumbers(numOfCores);
81 | System.out.println("Stream (" + numbers.size() + " elements)");
82 | final long start = System.currentTimeMillis();
83 | numbers
84 | .stream()
85 | .map(i -> {
86 | try {
87 | TimeUnit.SECONDS.sleep(1);
88 | } catch (InterruptedException e) {
89 | e.printStackTrace();
90 | }
91 | return i;
92 | })
93 | .forEach(i -> System.out.println(i));
94 | System.out.println(System.currentTimeMillis() - start);
95 |
96 | }
97 |
98 | public void test(int num) {
99 | System.out.println("System.setProperty(\"java.util.concurrent.ForkJoinPool.common.parallelism\", \"" + num +
100 | "\"): " + System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", String.valueOf(num)));
101 |
102 | parallelStreamTest(8);
103 | }
104 |
105 | private static void parallelStreamTest(int numOfCores) {
106 |
107 | System.out.println("\n==========================================");
108 | System.out.println("StreamExamples5Parallel.parallelStreamTest");
109 | final List numbers = getNumbers(numOfCores);
110 |
111 | System.out.println("Parallel Stream (" + numbers.size() + " elements)");
112 | final long start2 = System.currentTimeMillis();
113 | numbers.parallelStream()
114 | .map(i -> {
115 | try {
116 | TimeUnit.SECONDS.sleep(1);
117 | } catch (InterruptedException e) {
118 | e.printStackTrace();
119 | }
120 | return i;
121 | })
122 | .forEach(i -> System.out.println(i));
123 | System.out.println(System.currentTimeMillis() - start2);
124 | }
125 |
126 | private static List getNumbers(final int howMany) {
127 | return IntStream.rangeClosed(1, howMany)
128 | .mapToObj(i -> i) // auto-boxing을 통해서 int 가 Integer로 자동변환 됩니다.
129 | .collect(toList());
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e08_03_stream_05_parallel/StreamExamples5ParallelPerformance.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e08_03_stream_05_parallel;
2 |
3 | import java.util.concurrent.TimeUnit;
4 | import java.util.stream.LongStream;
5 | import java.util.stream.Stream;
6 |
7 | /**
8 | * @author Kevin Lee
9 | * @since 2015-08-23
10 | */
11 | public class StreamExamples5ParallelPerformance {
12 |
13 | private static void slowDown() {
14 | try {
15 | TimeUnit.MILLISECONDS.sleep(10L);
16 | } catch (InterruptedException e) {
17 | e.printStackTrace();
18 | }
19 | }
20 |
21 | public static long iterativeSum(long n) {
22 | long result = 0;
23 | for (long i = 0; i <= n; i++) {
24 | result += i;
25 | slowDown();
26 | }
27 | return result;
28 | }
29 |
30 | public static long sequentialSum(long n) {
31 | return Stream.iterate(1L, i -> i + 1).limit(n).peek(i -> slowDown()).reduce(Long::sum).get();
32 | }
33 |
34 | public static long parallelSum(long n) {
35 | return Stream.iterate(1L, i -> i + 1).limit(n).parallel().peek(i -> slowDown()).reduce(Long::sum).get();
36 | }
37 |
38 | public static long rangedSum(long n) {
39 | return LongStream.rangeClosed(1, n).peek(i -> slowDown()).reduce(Long::sum).getAsLong();
40 | }
41 |
42 | public static long parallelRangedSum(long n) {
43 | return LongStream.rangeClosed(1, n).parallel().peek(i -> slowDown()).reduce(Long::sum).getAsLong();
44 | }
45 |
46 | public static void main(String[] args) {
47 | final long n = 1000;
48 | final long start = System.currentTimeMillis();
49 | // 1 + 2 + 3 + ... + 98 + 99 + 100
50 | System.out.println((1 + n) * (n / 2));
51 | System.out.println(" Gauss Way: " + (System.currentTimeMillis() - start));
52 |
53 | final long start1 = System.currentTimeMillis();
54 | System.out.println(" iterativeSum(n): " + iterativeSum(n));
55 | System.out.println(" " + (System.currentTimeMillis() - start1) + " ms\n");
56 | final long start2 = System.currentTimeMillis();
57 | System.out.println(" sequentialSum(n): " + sequentialSum(n));
58 | System.out.println(" " + (System.currentTimeMillis() - start2) + " ms\n");
59 | final long start3 = System.currentTimeMillis();
60 | System.out.println(" parallelSum(n): " + parallelSum(n));
61 | System.out.println(" " + (System.currentTimeMillis() - start3) + " ms\n");
62 | final long start4 = System.currentTimeMillis();
63 | System.out.println(" rangedSum(n): " + rangedSum(n));
64 | System.out.println(" " + (System.currentTimeMillis() - start4) + " ms\n");
65 | final long start5 = System.currentTimeMillis();
66 | System.out.println("parallelRangedSum(n): " + parallelRangedSum(n));
67 | System.out.println(" " + (System.currentTimeMillis() - start5) + " ms\n");
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e08_03_stream_05_parallel/StreamExamples5ParallelPerformancePractical.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e08_03_stream_05_parallel;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 |
6 | import java.math.BigDecimal;
7 | import java.util.*;
8 | import java.util.function.Predicate;
9 | import java.util.stream.Stream;
10 |
11 | /**
12 | * @author Kevin Lee
13 | * @since 2015-08-23
14 | */
15 | public class StreamExamples5ParallelPerformancePractical {
16 | private static final String[] priceStrings = {"1.0", "100.99", "35.75", "21.30", "88.00"};
17 | private static final BigDecimal[] targetPrices = {new BigDecimal("30"), new BigDecimal("20"), new BigDecimal("31")};
18 | private static final Random random = new Random(123);
19 | private static final Random targetPriceRandom = new Random(111);
20 |
21 | private static final List products;
22 |
23 | static {
24 | final int length = 8_000_000;
25 | final Product[] list = new Product[length];
26 |
27 | for (int i = 1; i <= length; i++) {
28 | list[i - 1] = new Product((long) i, "Product" + i, new BigDecimal(priceStrings[random.nextInt(5)]));
29 | }
30 | products = Collections.unmodifiableList(Arrays.asList(list));
31 | }
32 |
33 | private static BigDecimal imperativeSum(final List products, final Predicate predicate) {
34 | BigDecimal sum = BigDecimal.ZERO;
35 | for (final Product product : products) {
36 | if (predicate.test(product)) {
37 | sum = sum.add(product.getPrice());
38 | }
39 | }
40 | return sum;
41 | }
42 |
43 | private static BigDecimal streamSum(final Stream stream, final Predicate predicate) {
44 | return stream.filter(predicate).map(Product::getPrice).reduce(BigDecimal.ZERO, BigDecimal::add);
45 | }
46 |
47 | private static void imperativeTest(final BigDecimal targetPrice, final boolean printResult) {
48 | /**
49 | * Benchmark 코드라서 결코 일반 앱 개발등에 쓰기 좋은 코딩 스타일로 작성된것이 아닙니다.
50 | * (Stream사용 이외의) 이런 코드 작성을 절대 권장하지 않습니다.
51 | */
52 | if (printResult) {
53 | System.out.println("============================================");
54 | System.out.println("\nImperative Sum\n--------------------------------------------");
55 | }
56 | final long start = System.currentTimeMillis();
57 | final BigDecimal result = imperativeSum(products, product -> product.getPrice().compareTo(targetPrice) >= 0);
58 | final long howLong = System.currentTimeMillis() - start;
59 | if (printResult) {
60 | System.out.println("Sum: " + result);
61 | System.out.println("It took " + howLong + " ms.");
62 | System.out.println("============================================");
63 | }
64 | }
65 |
66 | private static void streamTest(final BigDecimal targetPrice, final boolean printResult) {
67 | /**
68 | * Benchmark 코드라서 결코 일반 앱 개발등에 쓰기 좋은 코딩 스타일로 작성된것이 아닙니다.
69 | * (Stream사용 이외의) 이런 코드 작성을 절대 권장하지 않습니다.
70 | */
71 | if (printResult) {
72 | System.out.println("============================================");
73 | System.out.println("\nStream Sum\n--------------------------------------------");
74 | }
75 | final long start = System.currentTimeMillis();
76 | final BigDecimal result = streamSum(products.stream(), product -> product.getPrice().compareTo(targetPrice) >= 0);
77 | final long howLong = System.currentTimeMillis() - start;
78 | if (printResult) {
79 | System.out.println("Sum: " + result);
80 | System.out.println("It took " + howLong + " ms.");
81 | System.out.println("============================================");
82 | }
83 | }
84 |
85 | private static void parallelStreamTest(final BigDecimal targetPrice, final boolean printResult) {
86 | /**
87 | * Benchmark 코드라서 결코 일반 앱 개발등에 쓰기 좋은 코딩 스타일로 작성된것이 아닙니다.
88 | * (Stream사용 이외의) 이런 코드 작성을 절대 권장하지 않습니다.
89 | */
90 | if (printResult) {
91 | System.out.println("============================================");
92 | System.out.println("\nParallel Stream Sum\n--------------------------------------------");
93 | }
94 | final long start = System.currentTimeMillis();
95 | final BigDecimal result = streamSum(products.parallelStream(), product -> product.getPrice().compareTo(targetPrice) >= 0);
96 | final long howLong = System.currentTimeMillis() - start;
97 | if (printResult) {
98 | System.out.println("Sum: " + result);
99 | System.out.println("It took " + howLong + " ms.");
100 | System.out.println("============================================");
101 | }
102 | }
103 |
104 | public static void main(String[] args) {
105 | /**
106 | * Benchmark 코드라서 결코 일반 앱 개발등에 쓰기 좋은 코딩 스타일로 작성된것이 아닙니다.
107 | * (Stream사용 이외의) 이런 코드 작성을 절대 권장하지 않습니다.
108 | */
109 | test1();
110 | test2();
111 | test3();
112 | }
113 |
114 | private static void test1() {
115 |
116 | final BigDecimal targetPrice = new BigDecimal("40");
117 |
118 | imperativeTest(targetPrice, false);
119 | streamTest(targetPrice, false);
120 | parallelStreamTest(targetPrice, false);
121 |
122 | System.out.println("\n\n================================================================\nTest1 Starts!");
123 | for (int i = 0; i < 5; i++) {
124 | BigDecimal price = targetPrices[targetPriceRandom.nextInt(3)];
125 |
126 | imperativeTest(price, true);
127 | streamTest(price, true);
128 | parallelStreamTest(price, true);
129 | }
130 | }
131 |
132 | private static void test2() {
133 |
134 | final BigDecimal targetPrice = new BigDecimal("40");
135 |
136 | parallelStreamTest(targetPrice, false);
137 | imperativeTest(targetPrice, false);
138 | streamTest(targetPrice, false);
139 |
140 | System.out.println("\n\n================================================================\nTest2 Starts!");
141 | for (int i = 0; i < 5; i++) {
142 | BigDecimal price = targetPrices[targetPriceRandom.nextInt(3)];
143 |
144 | parallelStreamTest(price, true);
145 | imperativeTest(price, true);
146 | streamTest(price, true);
147 | }
148 | }
149 |
150 | private static void test3() {
151 |
152 | final BigDecimal targetPrice = new BigDecimal("40");
153 |
154 | streamTest(targetPrice, false);
155 | parallelStreamTest(targetPrice, false);
156 | imperativeTest(targetPrice, false);
157 |
158 | System.out.println("\n\n================================================================\nTest3 Starts!");
159 | for (int i = 0; i < 5; i++) {
160 | BigDecimal price = targetPrices[targetPriceRandom.nextInt(3)];
161 |
162 | streamTest(price, true);
163 | parallelStreamTest(price, true);
164 | imperativeTest(price, true);
165 | }
166 | }
167 |
168 | }
169 |
170 | @AllArgsConstructor
171 | @Data
172 | class Product {
173 | private Long id;
174 | private String name;
175 | private BigDecimal price;
176 | }
177 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e09_closure/ClosureExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e09_closure;
2 |
3 | /**
4 | * @author Kevin Lee
5 | * @since 2015-09-13
6 | */
7 | public class ClosureExamples {
8 | private int number = 999;
9 |
10 | public static void main(String[] args) {
11 | new ClosureExamples().test3();
12 | }
13 |
14 |
15 | private void test() {
16 | int number = 100;
17 |
18 | testClosure("Anonymous Class", new Runnable() {
19 | @Override
20 | public void run() {
21 | System.out.println(number);
22 | }
23 | });
24 |
25 | testClosure("Lambda Expression", () -> System.out.println(number));
26 |
27 | }
28 | private void test1() {
29 | int number = 100;
30 |
31 | testClosure("Anonymous Class", new Runnable() {
32 | @Override
33 | public void run() {
34 | System.out.println(ClosureExamples.this.number);
35 | }
36 | });
37 |
38 | testClosure("Lambda Expression", () -> System.out.println(this.number));
39 |
40 | }
41 |
42 | private void test2() {
43 |
44 | testClosure("Anonymous Class", new Runnable() {
45 | @Override
46 | public void run() {
47 | System.out.println("this.toString(): " + this.toString());
48 | }
49 | });
50 |
51 | testClosure("Anonymous Class", new Runnable() {
52 | @Override
53 | public void run() {
54 | System.out.println("ClosureExamples.this.toString(): " + ClosureExamples.this.toString());
55 | }
56 | });
57 |
58 | testClosure("Lambda Expression", () -> System.out.println("this.toString(): " + this.toString()));
59 | }
60 |
61 | private void test3() {
62 |
63 | System.out.println("\"ClosureExamples calling toString()\": " + toString());
64 | System.out.println("\"ClosureExamples calling toString(int, String)\": " + toString(1, "Hello"));
65 |
66 | testClosure("Anonymous Class", new Runnable() {
67 | @Override
68 | public void run() {
69 | // System.out.println("toString(int, String): " + toString(1, "Test"));
70 | System.out.println("toString(int, String) causes compile-time error");
71 | System.out.println("ClosureExamples.this.toString(int, String): " + ClosureExamples.toString(1, "Test"));
72 | }
73 | });
74 | testClosure("Anonymous Class", new Runnable() {
75 | @Override
76 | public void run() {
77 | // System.out.println("toString(int): " + toString(1));
78 | System.out.println("toString(int) causes compile-time error");
79 | System.out.println("ClosureExamples.this.toString(int, String): " + ClosureExamples.this.toString(1));
80 | }
81 | });
82 |
83 | testClosure("Lambda Expression", () -> System.out.println("this.toString(int, String): " + this.toString(1, "Test")));
84 | testClosure("Lambda Expression", () -> System.out.println("toString(int, String): " + toString(1, "Test")));
85 | testClosure("Lambda Expression", () -> System.out.println("this.toString(int): " + this.toString(1)));
86 | testClosure("Lambda Expression", () -> System.out.println("toString(int): " + toString(1)));
87 | }
88 |
89 | private void test4() {
90 |
91 | int number = 100;
92 |
93 | testClosure("Anonymous Class", new Runnable() {
94 | @Override
95 | public void run() {
96 | int number = 50; // no compile-time error
97 | System.out.println(number);
98 | }
99 | });
100 |
101 | testClosure("Lambda Expression", () -> {
102 | // int number = 50; // compile-time error
103 | System.out.println(number);
104 | });
105 |
106 | }
107 |
108 | private static void testClosure(final String name, final Runnable runnable) {
109 | System.out.println("===================================");
110 | System.out.println(name + ": ");
111 | runnable.run();
112 | System.out.println("===================================");
113 | }
114 |
115 |
116 | @Override
117 | public String toString() {
118 | return new StringBuilder("ClosureExamples{")
119 | .append("number=")
120 | .append(number)
121 | .append('}')
122 | .toString();
123 | }
124 |
125 | public String toString(int number) {
126 | return "#" + number;
127 | }
128 |
129 | public static String toString(int number, T value) {
130 | return "[" + number + "] The value is " + String.valueOf(value) + ".";
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/e09_closure/ClosureExamples2.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e09_closure;
2 |
3 | /**
4 | * @author Kevin Lee
5 | * @since 2015-09-13
6 | */
7 | public class ClosureExamples2 {
8 | private int number = 999;
9 |
10 | public static void main(String[] args) {
11 | new ClosureExamples2().test();
12 | }
13 |
14 | private void test() {
15 | // int number = 100;
16 |
17 | Runnable runnable = new Runnable() {
18 | @Override
19 | public void run() {
20 | System.out.println(number);
21 | }
22 | };
23 | runnable.run();
24 |
25 | Runnable runnable1 = () -> System.out.println(number);
26 | runnable1.run();
27 |
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/ep10_higher_order_function/HigherOrderFunctionExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.ep10_higher_order_function;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.function.Function;
7 |
8 | import static java.util.stream.Collectors.toList;
9 |
10 | /**
11 | * @author Kevin Lee
12 | * @since 2015-10-25
13 | */
14 | public class HigherOrderFunctionExamples {
15 | public static void main(String[] args) {
16 |
17 | final Function, String> f = g -> g.apply(10);
18 | System.out.println(
19 | f.apply(i -> "#" + i) // "#10"
20 | );
21 |
22 | final Function> f2 = i -> i2 -> i + i2;
23 | System.out.println(
24 | f2.apply(1).apply(9) // 10
25 | );
26 |
27 | final List list = Arrays.asList(1, 2, 3, 4, 5);
28 | final List mappedList = map(list, i -> "#" + i);
29 | System.out.println(
30 | mappedList
31 | );
32 |
33 | System.out.println(
34 | list.stream()
35 | .filter(i -> i > 2)
36 | .map(i -> "#" + i)
37 | .collect(toList())
38 | );
39 |
40 |
41 | // Function.identity()
42 |
43 | Function>> f3 =
44 | i1 -> i2 -> i3 -> i1 + i2 + i3;
45 |
46 | System.out.println(
47 | "f3.apply(1).apply(2).apply(3) = " + f3.apply(1).apply(2).apply(3)
48 | );
49 |
50 | final Function> plus10 = f3.apply(10);
51 | System.out.println(
52 | "plus10.apply(1).apply(1) = " + plus10.apply(1).apply(1)
53 | );
54 |
55 | }
56 |
57 | private static List map(List list, Function mapper) {
58 | final List result = new ArrayList<>();
59 | for (final T t : list) {
60 | result.add(mapper.apply(t));
61 | }
62 | return result;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/ep11_method_reference/MethodReferenceExamples.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.ep11_method_reference;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.function.Function;
7 |
8 | import static java.util.stream.Collectors.toList;
9 |
10 | /**
11 | * @author Kevin Lee
12 | * @since 2015-11-01
13 | */
14 | public class MethodReferenceExamples {
15 | public static void main(String[] args) {
16 | Arrays.asList(1, 2, 3, 4, 5)
17 | .forEach(System.out::println);
18 | // .forEach(i -> System.out.println(i));
19 |
20 | System.out.println(
21 | Arrays.asList(new BigDecimal("10.0"), new BigDecimal("23"), new BigDecimal("5"))
22 | .stream()
23 | .sorted(BigDecimalUtil::compare)
24 | // .sorted((bd1, bd2) -> bd1.compareTo(bd2))
25 | .collect(toList())
26 | );
27 |
28 | System.out.println(
29 | Arrays.asList(new BigDecimal("10.0"), new BigDecimal("23"), new BigDecimal("5"))
30 | .stream()
31 | .sorted(BigDecimal::compareTo)
32 | // .sorted((bd1, bd2) -> bd1.compareTo(bd2))
33 | .collect(toList())
34 | );
35 |
36 |
37 | System.out.println("\nThe following three cases have the same result.");
38 | System.out.println("----------------------------------------------------");
39 | final List abcdList = Arrays.asList("a", "b", "c", "d");
40 | final String targetString = "c";
41 | System.out.println("list: " + abcdList);
42 | System.out.println("targetString: \"c\"");
43 | System.out.println("\nanyMatch(targetString::equals)\n" +
44 | abcdList
45 | .stream()
46 | .anyMatch(targetString::equals)
47 | );
48 | System.out.println("\nanyMatch(\"c\"::equals)\n" +
49 | abcdList
50 | .stream()
51 | .anyMatch("c"::equals)
52 | );
53 | System.out.println("\nanyMatch(x -> x.equals(\"c\"))\n" +
54 | abcdList
55 | .stream()
56 | .anyMatch(x -> x.equals("c"))
57 | );
58 |
59 | System.out.println("\n=========================================");
60 | System.out.println("methodReference03();");
61 | System.out.println("-----------------------------------------");
62 | methodReference03();
63 | }
64 |
65 | private static void methodReference03() {
66 | /* First Class Function */
67 | /**
68 | * A function can be passed as a parameter to another function.
69 | */
70 | /* Using Lambda Expression
71 | */
72 | System.out.println(testFirstClassFunction1(3, i -> String.valueOf(i * 2)));
73 | /*
74 | * Using Method Reference
75 | */
76 | System.out.println(testFirstClassFunction1(3, MethodReferenceExamples::doubleThenToString));
77 |
78 | /**
79 | * A function can be returned as the result of another function.
80 | */
81 | /*
82 | * Using Lambda Expression
83 | */
84 | final Function fl = getDoubleThenToStringUsingLambdaExpression();
85 | final String resultFromFl = fl.apply(3);
86 | System.out.println(resultFromFl);
87 | /*
88 | * Using Method Reference
89 | */
90 | final Function fmr = getDoubleThenToStringUsingMethodReference();
91 | final String resultFromFmr = fmr.apply(3);
92 | System.out.println(resultFromFmr);
93 |
94 | System.out.println("\n-----------------------------------------");
95 | /**
96 | * A function can be stored in the data structure.
97 | */
98 | /*
99 | * Using Lambda Expression
100 | */
101 | final List> fsL = Arrays.asList(i -> String.valueOf(i * 2));
102 | // Eclipse에 버그가 있는지 바로 윗줄의 코드가 정상 컴파일 되지 않는거 같습니다 만약 그럴 경우 아래 코드를 이용해 주세요.
103 | // 하지만 바로 윗줄 코드는 정상적인 코드입니다. Eclipse 버그 인거 같아요.
104 | // final List> fsL = Arrays.>asList(i -> String.valueOf(i * 2));
105 |
106 | for (final Function f : fsL) {
107 | final String result = f.apply(3);
108 | System.out.println(result);
109 | }
110 | /*
111 | * Using Method Reference
112 | */
113 | final List> fsMr = Arrays.asList(MethodReferenceExamples::doubleThenToString);
114 | for (final Function f : fsMr) {
115 | final String result = f.apply(3);
116 | System.out.println(result);
117 | }
118 |
119 | System.out.println("\n-----------------------------------------");
120 | /*
121 | * Using Lambda Expression
122 | */
123 | final Function fl2 = i -> String.valueOf(i * 2);
124 | final String resultFl2 = fl2.apply(5);
125 | System.out.println(resultFl2);
126 |
127 | /*
128 | * Method Reference
129 | */
130 | final Function fmr2 = MethodReferenceExamples::doubleThenToString;
131 | final String resultFmr2 = fmr2.apply(5);
132 | System.out.println(resultFmr2);
133 |
134 | System.out.println("\n-----------------------------------------");
135 | /*
136 | * Both Lambda Expression and Method Reference
137 | */
138 | final List> fsBoth =
139 | Arrays.asList(
140 | i -> String.valueOf(i * 2),
141 | MethodReferenceExamples::doubleThenToString,
142 | MethodReferenceExamples::addHashPrefix
143 | );
144 |
145 | for (final Function f : fsBoth) {
146 | final String result = f.apply(7);
147 | System.out.println(result);
148 | }
149 | }
150 |
151 | private static String doubleThenToString(int i) {
152 | return String.valueOf(i * 2);
153 | }
154 |
155 | private static String addHashPrefix(int number) {
156 | return "#" + number;
157 | }
158 |
159 | private static String testFirstClassFunction1(int n, Function f) {
160 | return "The result is " + f.apply(n) + ".";
161 | }
162 |
163 | private static Function getDoubleThenToStringUsingLambdaExpression() {
164 | return i -> String.valueOf(i * 2);
165 | }
166 |
167 | public static Function getDoubleThenToStringUsingMethodReference() {
168 | return MethodReferenceExamples::doubleThenToString;
169 | }
170 | }
171 |
172 | class BigDecimalUtil {
173 | public static int compare(BigDecimal bd1, BigDecimal bd2) {
174 | return bd1.compareTo(bd2);
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/ep11_method_reference/MethodReferenceExamples2Constructor.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.ep11_method_reference;
2 |
3 | import lombok.AllArgsConstructor;
4 | import lombok.Data;
5 |
6 | import java.math.BigDecimal;
7 | import java.util.function.Function;
8 |
9 | /**
10 | * @author Kevin Lee
11 | * @since 2016-01-17
12 | */
13 | public class MethodReferenceExamples2Constructor {
14 | public static void main(String[] args) {
15 | final Section section1 = new Section(1);
16 |
17 | final Function sectionFactoryWithLambdaExpression = number -> new Section(number);
18 | final Section section1WithLambdaExpression = sectionFactoryWithLambdaExpression.apply(1);
19 |
20 | final Function sectionFactoryWithMethodReference = Section::new;
21 | final Section section1WithMethodReference = sectionFactoryWithMethodReference.apply(1);
22 |
23 | System.out.println(section1);
24 | System.out.println(section1WithLambdaExpression);
25 | System.out.println(section1WithMethodReference);
26 |
27 | System.out.println("==================================\n");
28 |
29 | final OldProduct product = new OldProduct(1L, "A", new BigDecimal("100"));
30 | System.out.println(product);
31 |
32 | final OldProductCreator productCreator = OldProduct::new;
33 | System.out.println(productCreator.create(1L, "A", new BigDecimal("100")));
34 |
35 | System.out.println("==================================\n");
36 | final ProductA a = createProduct(1L, "A", new BigDecimal("123"), ProductA::new);
37 | final ProductB b = createProduct(2L, "B", new BigDecimal("111"), ProductB::new);
38 | final ProductC c = createProduct(3L, "C", new BigDecimal("10"), ProductC::new);
39 |
40 | System.out.println(a);
41 | System.out.println(b);
42 | System.out.println(c);
43 | }
44 |
45 | private static T createProduct(final Long id,
46 | final String name,
47 | final BigDecimal price,
48 | final ProductCreator productCreator) {
49 | if (id == null || id < 1L) {
50 | throw new IllegalArgumentException("The id must be a positive Long.");
51 | }
52 | if (name == null || name.isEmpty()) {
53 | throw new IllegalArgumentException("The name is not given.");
54 | }
55 | if (price == null || price.compareTo(BigDecimal.ZERO) <= 0) { // price <= ZERO
56 | throw new IllegalArgumentException("The price must be greater then 0.");
57 | }
58 | return productCreator.create(id, name, price);
59 | }
60 | }
61 |
62 |
63 | @FunctionalInterface
64 | interface OldProductCreator {
65 | OldProduct create(Long id, String name, BigDecimal price);
66 | }
67 |
68 | @FunctionalInterface
69 | interface ProductCreator {
70 | T create(Long id, String name, BigDecimal price);
71 | }
72 |
73 | @AllArgsConstructor
74 | @Data
75 | class Section {
76 | private int number;
77 | }
78 |
79 | @AllArgsConstructor
80 | @Data
81 | class OldProduct {
82 | private Long id;
83 | private String name;
84 | private BigDecimal price;
85 | }
86 |
87 | @AllArgsConstructor
88 | @Data
89 | abstract class Product {
90 | private Long id;
91 | private String name;
92 | private BigDecimal price;
93 | }
94 |
95 | class ProductA extends Product {
96 |
97 | public ProductA(final Long id, final String name, final BigDecimal price) {
98 | super(id, name, price);
99 | }
100 |
101 | @Override
102 | public String toString() {
103 | return "A=" + super.toString();
104 | }
105 | }
106 |
107 | class ProductB extends Product {
108 |
109 | public ProductB(final Long id, final String name, final BigDecimal price) {
110 | super(id, name, price);
111 | }
112 |
113 | @Override
114 | public String toString() {
115 | return "B=" + super.toString();
116 | }
117 | }
118 |
119 | class ProductC extends Product {
120 |
121 | public ProductC(final Long id, final String name, final BigDecimal price) {
122 | super(id, name, price);
123 | }
124 |
125 | @Override
126 | public String toString() {
127 | return "C=" + super.toString();
128 | }
129 | }
130 |
--------------------------------------------------------------------------------
/src/main/java/cc/kevinlee/modernjava/ep11_method_reference/MethodReferenceExamples3Array.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.ep11_method_reference;
2 |
3 | import java.lang.reflect.Array;
4 | import java.util.Arrays;
5 | import java.util.List;
6 | import java.util.function.Function;
7 | import java.util.function.IntFunction;
8 | import java.util.stream.Stream;
9 |
10 | import static java.util.stream.Collectors.toList;
11 |
12 | /**
13 | * @author Kevin Lee
14 | * @since 2016-01-17
15 | */
16 | public class MethodReferenceExamples3Array {
17 | public static void main(String[] args) {
18 | final String[] array = new String[5];
19 | System.out.println(array.length);
20 |
21 | final Function arrayFactoryLe = i -> new String[i];
22 | final String[] arrayCreatedByLambdaExpression = arrayFactoryLe.apply(7);
23 | System.out.println(arrayCreatedByLambdaExpression.length);
24 |
25 | final Function arrayFactoryMr = String[]::new;
26 | final String[] arrayCreatedByMethodReference = arrayFactoryMr.apply(10);
27 | System.out.println(arrayCreatedByMethodReference.length);
28 |
29 | final IntFunction arrayFactoryMr2 = String[]::new;
30 | final String[] arrayCreatedByMethodReference2 = arrayFactoryMr2.apply(11);
31 | System.out.println(arrayCreatedByMethodReference2.length);
32 |
33 | final Integer[] integers = Stream.of(1, 2, 3, 4, 5)
34 | .map(i -> i * 2)
35 | .toArray(Integer[]::new);
36 | System.out.println(Arrays.toString(integers));
37 |
38 | final String[] strings = Stream.of("A", "B", "C")
39 | .toArray(String[]::new);
40 | // .toArray(i -> new String[i]);
41 | System.out.println(Arrays.toString(strings));
42 |
43 | final List integers2 = Arrays.asList(1, 2, 3, 4, 5);
44 |
45 | final Integer[] integerArray2 = integers2.toArray(new Integer[0]);
46 | System.out.println(Arrays.toString(integerArray2));
47 |
48 | // final String[] stringArray2 = integers2.toArray(new String[0]); // no compile-time error
49 | // System.out.println(Arrays.toString(stringArray2)); // runtime error
50 |
51 | // final List ss = integers2.stream().collect(toList()); // compile-time error
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/test/java/cc/kevinlee/modernjava/e01/CalculatorServiceTest.java:
--------------------------------------------------------------------------------
1 | package cc.kevinlee.modernjava.e01;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.assertj.core.api.Assertions.*;
6 |
7 | /**
8 | * @author Kevin Lee
9 | * @since 2015-08-02
10 | */
11 | public class CalculatorServiceTest {
12 |
13 | @Test
14 | public void testCalculateAddition() throws Exception {
15 | final Calculation calculation = (i1, i2) -> i1 + i2;
16 |
17 | final int actual = calculation.calculate(1, 1);
18 |
19 | assertThat(actual).isEqualTo(2);
20 | }
21 |
22 | @Test
23 | public void testCalculateSubtraction() throws Exception {
24 | final Calculation calculation = new Subtraction();
25 |
26 | final int actual = calculation.calculate(1, 1);
27 |
28 | assertThat(actual).isEqualTo(0);
29 | }
30 |
31 | @Test
32 | public void testCalculateMultiplication() throws Exception {
33 | final Calculation calculation = new Multiplication();
34 |
35 | final int actual = calculation.calculate(1, 1);
36 |
37 | assertThat(actual).isEqualTo(1);
38 | }
39 |
40 | @Test
41 | public void testCalculateDivision() throws Exception {
42 | final Calculation calculation = new Division();
43 |
44 | final int actual = calculation.calculate(8, 0);
45 |
46 | assertThat(actual).isEqualTo(2);
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------