├── .gitignore
├── README.md
├── license.txt
├── pom.xml
└── src
├── main
├── java
│ └── com
│ │ └── nurkiewicz
│ │ ├── java8
│ │ ├── FutureOps.java
│ │ ├── MultiRunner.java
│ │ ├── RandomSource.java
│ │ ├── agent
│ │ │ ├── Agent.java
│ │ │ └── AsyncAgent.java
│ │ ├── atomic
│ │ │ ├── BigDecimalAccumulator.java
│ │ │ ├── EventCounter.java
│ │ │ ├── RangeCollector.java
│ │ │ └── SafeCalculator.java
│ │ ├── defmethods
│ │ │ ├── Engine.java
│ │ │ ├── Job.java
│ │ │ ├── Lifecycle.java
│ │ │ └── RuleEngine.java
│ │ ├── holidays
│ │ │ ├── AmericanHolidays.java
│ │ │ ├── Easter.java
│ │ │ ├── Holidays.java
│ │ │ ├── HolidaysFactory.java
│ │ │ └── PolishHolidays.java
│ │ ├── interfaces
│ │ │ ├── Encrypter.java
│ │ │ ├── ReverseEncrypter.java
│ │ │ ├── RotEncrypter.java
│ │ │ └── XorEncrypter.java
│ │ ├── people
│ │ │ ├── Person.java
│ │ │ ├── PersonDao.java
│ │ │ ├── PersonService.java
│ │ │ ├── Phone.java
│ │ │ └── Sex.java
│ │ ├── stackoverflow
│ │ │ ├── ArtificialSleepWrapper.java
│ │ │ ├── FallbackStubClient.java
│ │ │ ├── HttpStackOverflowClient.java
│ │ │ ├── InjectErrorsWrapper.java
│ │ │ ├── LoadFromStackOverflowTask.java
│ │ │ ├── LoggingWrapper.java
│ │ │ ├── Question.java
│ │ │ └── StackOverflowClient.java
│ │ └── util
│ │ │ ├── LoremIpsum.java
│ │ │ └── PrimeUtil.java
│ │ └── rxjava
│ │ ├── ObservableOps.java
│ │ └── util
│ │ └── Indexed.java
└── resources
│ ├── clojure-questions.html
│ ├── groovy-questions.html
│ ├── java-questions.html
│ ├── lorem-ipsum.txt
│ ├── people.csv
│ └── scala-questions.html
└── test
└── java
└── com
└── nurkiewicz
├── java8
├── J01_HelloWorldTest.java
├── J02_InterfacesTest.java
├── J02b_ConflictingDefaultMethodsTest.java
├── J03_FunctionTest.java
├── J04_FunctionalInterfacesTest.java
├── J05_MultiRunnerTest.java
├── J06_OptionalTest.java
├── J07_StreamsTest.java
├── J07b_StreamReduceTest.java
├── J07c_StreamInfiniteTest.java
├── J07d_CustomCollectorTest.java
├── J08_FilesTest.java
├── J08_LocalDateTest.java
├── J08_NewMapMethodsTest.java
├── J09_CollectorsTest.java
├── J09_StringsTest.java
├── J10_ParallelStreamsTest.java
├── J11_AtomicTest.java
├── J11b_AtomicTest.java
├── J11c_AtomicTest.java
├── J12_BigDecimalAccumulatorTest.java
├── J13_AsyncAgentTest.java
├── J21_FuturesIntroductionTest.java
├── J22_CreatingTest.java
├── J23_MapTest.java
├── J24_FlatMapTest.java
├── J25_ZipTest.java
├── J26_AllAnyTest.java
├── J27_PromisesTest.java
├── J28_CustomFutureOperatorsTest.java
├── J29_AsyncAgentFuturesTest.java
├── J60_CovarianceTest.java
├── holidays
│ ├── EasterTest.java
│ ├── HolidaysFactoryTest.java
│ └── PolishHolidaysTest.java
└── util
│ └── AbstractFuturesTest.java
└── rxjava
├── R41_IntroductionTest.java
├── R42_CreatingTest.java
├── R43_ListeningTest.java
├── R45_FilteringTest.java
├── R46_ComposingTest.java
├── R47_IndexingTest.java
├── R48_CompletableFutureAndObservable.java
├── R49_TransformingTest.java
├── R50_OperatorsTest.java
├── R51_InfiniteObservableTest.java
├── util
└── HeartBeat.java
└── weather
├── Weather.java
├── WeatherStation.java
└── WeatherStationStub.java
/.gitignore:
--------------------------------------------------------------------------------
1 | target
2 | *.iml
3 | .idea
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Java 8 and RxJava workshop driven by tests
2 |
3 | ## Smoke testing
4 |
5 | ### Maven
6 |
7 | Run `mvn clean test` to make sure you have JDK 8 and all dependencies in place.
8 |
9 | ### IDE
10 |
11 | Run `J01_HelloWorldTest.java` from your favourite IDE and make sure it compiles and passes.
12 |
13 | ## Troubleshooting
14 |
15 | ### Error `invalid target release: 1.8` during maven build
16 |
17 | If you see this error message during maven build:
18 |
19 | [INFO] BUILD FAILURE
20 | ...
21 | [ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.1:compile (default-compile) on project java8:
22 | Fatal error compiling: invalid target release: 1.8 -> [Help 1]
23 |
24 | it means you are not compiling using Java 8. Download JDK 8 and let maven use it:
25 |
26 | $ export JAVA_HOME=/path/to/jdk8
27 |
28 | ## License
29 | This project is released under version 2.0 of the [Apache License](http://www.apache.org/licenses/LICENSE-2.0).
30 |
--------------------------------------------------------------------------------
/license.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 | 4.0.0
3 |
4 | Java 8 workshop
5 | com.nurkiewicz
6 | java8
7 | 0.0.1-SNAPSHOT
8 |
9 |
10 | Apache License, Version 2.0
11 | http://www.apache.org/licenses/LICENSE-2.0
12 |
13 |
14 |
15 |
16 | UTF-8
17 |
18 |
19 |
20 |
21 |
22 |
23 | com.google.guava
24 | guava
25 | 16.0
26 |
27 |
28 | commons-io
29 | commons-io
30 | 2.4
31 |
32 |
33 | com.netflix.rxjava
34 | rxjava-core
35 | 0.18.1
36 |
37 |
38 |
39 |
40 | ch.qos.logback
41 | logback-classic
42 | 1.0.13
43 |
44 |
45 | org.slf4j
46 | jul-to-slf4j
47 | 1.7.5
48 |
49 |
50 | org.slf4j
51 | log4j-over-slf4j
52 | 1.7.5
53 |
54 |
55 | org.slf4j
56 | jcl-over-slf4j
57 | 1.7.5
58 |
59 |
60 | commons-logging
61 | commons-logging
62 | 1.1.3
63 | provided
64 |
65 |
66 | javax.jms
67 | javax.jms-api
68 | 2.0
69 |
70 |
71 | org.jsoup
72 | jsoup
73 | 1.7.3
74 |
75 |
76 | org.springframework
77 | spring-web
78 | 3.2.4.RELEASE
79 |
80 |
81 |
82 |
83 | junit
84 | junit
85 | 4.11
86 | test
87 |
88 |
89 | org.easytesting
90 | fest-assert-core
91 | 2.0M9
92 | test
93 |
94 |
95 | pl.pragmatists
96 | JUnitParams
97 | 1.0.3
98 | test
99 |
100 |
101 | org.mockito
102 | mockito-all
103 | 1.9.5
104 |
105 |
106 | com.jayway.awaitility
107 | awaitility
108 | 1.6.0
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | maven-compiler-plugin
117 | 3.1
118 |
119 | 1.8
120 | 1.8
121 |
122 |
123 |
124 |
125 |
126 |
127 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/FutureOps.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import java.time.Duration;
4 | import java.util.List;
5 | import java.util.concurrent.CompletableFuture;
6 | import java.util.concurrent.Future;
7 | import java.util.concurrent.TimeoutException;
8 |
9 | public class FutureOps {
10 |
11 | public static CompletableFuture failed(Throwable t) {
12 | final CompletableFuture future = new CompletableFuture();
13 | future.completeExceptionally(t);
14 | return future;
15 | }
16 |
17 | public static CompletableFuture never() {
18 | throw new UnsupportedOperationException("never()");
19 | }
20 |
21 | /**
22 | * Fails with {@link TimeoutException} after given time
23 | */
24 | public static CompletableFuture timeoutAfter(Duration duration) {
25 | throw new UnsupportedOperationException("timeoutAfter()");
26 | }
27 |
28 | /**
29 | * Should not block but return {@link CompletableFuture} immediately.
30 | */
31 | public static CompletableFuture toCompletable(Future future) {
32 | throw new UnsupportedOperationException("toCompletable()");
33 | }
34 |
35 | /**
36 | * Filters out futures that failed. Preserves order of input, no matter what was the completion order
37 | */
38 | public static CompletableFuture> ignoreFailures(List> futures) {
39 | throw new UnsupportedOperationException("ignoreFailures()");
40 | }
41 |
42 | /**
43 | * Takes a {@link CompletableFuture} and returns compatible future, but that completes with delay.
44 | * E.g. if underlying future completes after 7 seconds, and we call this method with 2 seconds duration,
45 | * resulting future will complete after 9 seconds.
46 | * @return {@link CompletableFuture} which completes after underlying future with given duration
47 | */
48 | public static CompletableFuture delay(CompletableFuture future, Duration duration) {
49 | throw new UnsupportedOperationException("delay()");
50 | }
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/MultiRunner.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.google.common.util.concurrent.ThreadFactoryBuilder;
4 |
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.Executors;
7 | import java.util.concurrent.ThreadFactory;
8 |
9 | /**
10 | * Uses dirty static methods on purpose, so that it's easier to use during testing.
11 | */
12 | public class MultiRunner {
13 |
14 | public static final int THREAD_COUNT = 20;
15 |
16 | private static final ExecutorService POOL = Executors.newFixedThreadPool(THREAD_COUNT, threadFactory());
17 |
18 | private static ThreadFactory threadFactory() {
19 | return new ThreadFactoryBuilder()
20 | .setDaemon(true)
21 | .setNameFormat("Multi-%d")
22 | .build();
23 | }
24 |
25 | public static void runMultiThreaded(Runnable block) {
26 | runMultiThreaded(1, block);
27 | }
28 |
29 | /**
30 | * Runs blocks given number of times.
31 | * Equivalent to replicating block number of times into Iterable and passing to {@link #runMultiThreaded(Iterable)}
32 | *
33 | * @param times How many times to execute it
34 | * @param block Code to execute
35 | */
36 | public static void runMultiThreaded(int times, Runnable block) {
37 | throw new UnsupportedOperationException("runMultiThreaded()");
38 | }
39 |
40 | /**
41 | * Runs all given blocks of code, possibly multi-threaded
42 | *
43 | * @param blocks Blocks of code to execute in a thread pool, each one only once
44 | */
45 | public static void runMultiThreaded(Iterable blocks) {
46 | throw new UnsupportedOperationException("runMultiThreaded()");
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/RandomSource.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | @FunctionalInterface
4 | interface RandomSource {
5 |
6 | int oneOrMinusOne();
7 |
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/agent/Agent.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.agent;
2 |
3 | import java.util.concurrent.CompletableFuture;
4 | import java.util.function.Predicate;
5 | import java.util.function.UnaryOperator;
6 |
7 | /**
8 | * A wrapper around any object that asynchronously serializes all modifications one after another.
9 | * Agent guarantees that at any given time only one transformation is happening.
10 | * I.e. if two threads send modification at the same time, they are applied sequentially, in another thread.
11 | * Value inside agent is replaced by the result of transformation. However you might as well mutate such object and return it.
12 | *
13 | * @param Type of underlying value, must be immutable.
14 | * @see Clojure agents
15 | */
16 | public interface Agent {
17 |
18 | T get();
19 |
20 | /**
21 | * Changes the underlying value of agent asynchronously.
22 | * Supplied function will be executed later in another thread.
23 | *
24 | * @param transformFun Function that will be executed against current value.
25 | * Its outcome will replace current value.
26 | */
27 | void send(UnaryOperator transformFun);
28 |
29 | CompletableFuture sendAndGet(UnaryOperator transformFun);
30 |
31 | /**
32 | * Returns value after all already sent operations were processed.
33 | * Result of this method will see changes made by all prior modifications.
34 | *
35 | * @return Future that completes when all previous tasks complete.
36 | */
37 | CompletableFuture getAsync();
38 |
39 | CompletableFuture completeIf(Predicate predicate);
40 |
41 | static Agent create(T initial) {
42 | return new AsyncAgent<>(initial);
43 | }
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/agent/AsyncAgent.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.agent;
2 |
3 | import java.util.concurrent.CompletableFuture;
4 | import java.util.function.Predicate;
5 | import java.util.function.UnaryOperator;
6 |
7 | public class AsyncAgent implements Agent {
8 |
9 | public AsyncAgent() {
10 | }
11 |
12 | public AsyncAgent(T initial) {
13 | }
14 |
15 | @Override
16 | public T get() {
17 | throw new UnsupportedOperationException("get()");
18 | }
19 |
20 | @Override
21 | public void send(UnaryOperator transformFun) {
22 | throw new UnsupportedOperationException("send()");
23 | }
24 |
25 | @Override
26 | public CompletableFuture sendAndGet(UnaryOperator transformFun) {
27 | throw new UnsupportedOperationException("sendAndGet()");
28 | }
29 |
30 | @Override
31 | public CompletableFuture getAsync() {
32 | throw new UnsupportedOperationException("getAsync()");
33 | }
34 |
35 | @Override
36 | public CompletableFuture completeIf(Predicate predicate) {
37 | throw new UnsupportedOperationException("completeIf()");
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/atomic/BigDecimalAccumulator.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.atomic;
2 |
3 | import java.math.BigDecimal;
4 | import java.util.function.BinaryOperator;
5 |
6 | public class BigDecimalAccumulator {
7 |
8 | private final BinaryOperator accFun;
9 |
10 | public BigDecimalAccumulator(BigDecimal initialValue, BinaryOperator accFun) {
11 | this(initialValue, accFun, availCpuMin4());
12 | }
13 |
14 | public BigDecimalAccumulator(BigDecimal initialValue, BinaryOperator accFun, int concurrency) {
15 | this.accFun = accFun;
16 | }
17 |
18 | private static int availCpuMin4() {
19 | return Math.max(Runtime.getRuntime().availableProcessors(), 4);
20 | }
21 |
22 | public BigDecimal get() {
23 | throw new UnsupportedOperationException("get()");
24 | }
25 |
26 | public void accumulate(BigDecimal value) {
27 | throw new UnsupportedOperationException("accumulate()");
28 | }
29 |
30 | public void reset() {
31 | throw new UnsupportedOperationException("reset()");
32 | }
33 |
34 | public BigDecimal getAndReset() {
35 | throw new UnsupportedOperationException("getAndReset()");
36 | }
37 |
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/atomic/EventCounter.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.atomic;
2 |
3 | public class EventCounter extends Number {
4 |
5 | public long incBy(long x) {
6 | throw new UnsupportedOperationException("incBy()");
7 | }
8 |
9 | public long reset() {
10 | throw new UnsupportedOperationException("reset()");
11 | }
12 |
13 | @Override
14 | public int intValue() {
15 | throw new UnsupportedOperationException("intValue()");
16 | }
17 |
18 | @Override
19 | public long longValue() {
20 | throw new UnsupportedOperationException("longValue()");
21 | }
22 |
23 | @Override
24 | public float floatValue() {
25 | throw new UnsupportedOperationException("floatValue()");
26 | }
27 |
28 | @Override
29 | public double doubleValue() {
30 | throw new UnsupportedOperationException("doubleValue()");
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/atomic/RangeCollector.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.atomic;
2 |
3 | public class RangeCollector {
4 |
5 | public void save(double x) {
6 | throw new UnsupportedOperationException("save()");
7 | }
8 |
9 | public double getMin() {
10 | throw new UnsupportedOperationException("getMin()");
11 | }
12 |
13 | public double getMax() {
14 | throw new UnsupportedOperationException("getMax()");
15 | }
16 |
17 | }
18 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/atomic/SafeCalculator.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.atomic;
2 |
3 | public class SafeCalculator extends Number {
4 |
5 | /**
6 | * Sets new value
7 | * @return Previous value
8 | */
9 | public int set(int x) {
10 | throw new UnsupportedOperationException("reset()");
11 | }
12 |
13 | public int mul(int x) {
14 | throw new UnsupportedOperationException("inc()");
15 | }
16 |
17 | public int div(int x) {
18 | throw new UnsupportedOperationException("div()");
19 | }
20 |
21 | public int add(int x) {
22 | throw new UnsupportedOperationException("add()");
23 | }
24 |
25 | public int sub(int x) {
26 | throw new UnsupportedOperationException("sub()");
27 | }
28 |
29 | @Override
30 | public int intValue() {
31 | throw new UnsupportedOperationException("intValue()");
32 | }
33 |
34 | @Override
35 | public long longValue() {
36 | throw new UnsupportedOperationException("longValue()");
37 | }
38 |
39 | @Override
40 | public float floatValue() {
41 | throw new UnsupportedOperationException("floatValue()");
42 | }
43 |
44 | @Override
45 | public double doubleValue() {
46 | throw new UnsupportedOperationException("doubleValue()");
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/defmethods/Engine.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.defmethods;
2 |
3 | public interface Engine {
4 |
5 | /**
6 | * Do not TOUCH!
7 | */
8 | default String start() {
9 | return "Engine";
10 | }
11 |
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/defmethods/Job.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.defmethods;
2 |
3 |
4 | public interface Job {
5 |
6 | /**
7 | * Do not TOUCH!
8 | */
9 | default String start() {
10 | return "Job";
11 | }
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/defmethods/Lifecycle.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.defmethods;
2 |
3 | public interface Lifecycle {
4 |
5 | /**
6 | * Do not TOUCH!
7 | */
8 | default String start() {
9 | return "Lifecycle";
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/defmethods/RuleEngine.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.defmethods;
2 |
3 | public class RuleEngine {
4 |
5 | public String start() {
6 | return "RuleEngine";
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/holidays/AmericanHolidays.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.holidays;
2 |
3 | import java.time.DayOfWeek;
4 | import java.time.LocalDate;
5 |
6 | public class AmericanHolidays implements Holidays {
7 | @Override
8 | public boolean isHoliday(LocalDate date) {
9 | return date.getDayOfWeek() == DayOfWeek.SATURDAY ||
10 | date.getDayOfWeek() == DayOfWeek.SUNDAY;
11 | }
12 |
13 | @Override
14 | public boolean isWorkingDay(LocalDate date) {
15 | return !isHoliday(date);
16 | }
17 |
18 | @Override
19 | public LocalDate nextHolidayAfter(LocalDate date) {
20 | LocalDate cur = date;
21 | do {
22 | cur = cur.plusDays(1);
23 | } while (isWorkingDay(cur));
24 | return cur;
25 | }
26 |
27 | @Override
28 | public LocalDate nextWorkingDayAfter(LocalDate date) {
29 | LocalDate cur = date;
30 | do {
31 | cur = cur.plusDays(1);
32 | } while (isHoliday(cur));
33 | return cur;
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/holidays/Easter.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.holidays;
2 |
3 | import java.time.LocalDate;
4 | import java.time.Year;
5 |
6 | class Easter {
7 |
8 | static LocalDate sundayFor(Year year) {
9 | final int y = year.getValue();
10 | final int a = y % 19;
11 | final int b = y / 100;
12 | final int c = y % 100;
13 | final int d = b / 4;
14 | final int e = b % 4;
15 | final int f = (b + 8) / 25;
16 | final int g = (b - f + 1) / 3;
17 | final int h = (19 * a + b - d - g + 15) % 30;
18 | final int i = c / 4;
19 | final int k = c % 4;
20 | final int m = (32 + 2 * e + 2 * i - h - k) % 7;
21 | final int n = (a + 11 * h + 22 * m) / 451;
22 | final int month = (h + m - 7 * n + 114) / 31;
23 | final int day = (((h + m - (7 * n) + 114) % 31) + 1);
24 | return LocalDate.of(y, month, day);
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/holidays/Holidays.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.holidays;
2 |
3 | import java.time.LocalDate;
4 |
5 | public interface Holidays {
6 |
7 | boolean isHoliday(LocalDate date);
8 |
9 | /**
10 | * Complementary to {@link #isHoliday(LocalDate)}.
11 | * @return !{@link #isHoliday(LocalDate)}
12 | */
13 | boolean isWorkingDay(LocalDate date);
14 |
15 | LocalDate nextHolidayAfter(LocalDate date);
16 |
17 | LocalDate nextWorkingDayAfter(LocalDate date);
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/holidays/HolidaysFactory.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.holidays;
2 |
3 | import java.util.Locale;
4 |
5 | public class HolidaysFactory {
6 |
7 | public static Holidays of(Locale locale) {
8 | switch (locale.getCountry()) {
9 | case "PL":
10 | return new PolishHolidays();
11 | case "US":
12 | return new AmericanHolidays();
13 | default:
14 | throw new IllegalArgumentException("Unsupported: " + locale.getCountry());
15 | }
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/holidays/PolishHolidays.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.holidays;
2 |
3 | import com.google.common.collect.ImmutableSet;
4 |
5 | import java.time.DayOfWeek;
6 | import java.time.LocalDate;
7 | import java.time.MonthDay;
8 | import java.time.Year;
9 | import java.util.Set;
10 |
11 | import static java.time.Month.AUGUST;
12 | import static java.time.Month.DECEMBER;
13 | import static java.time.Month.JANUARY;
14 | import static java.time.Month.MAY;
15 | import static java.time.Month.NOVEMBER;
16 |
17 | public class PolishHolidays implements Holidays {
18 |
19 | private static final Set FIXED_HOLIDAYS = ImmutableSet.of(
20 | MonthDay.of(JANUARY, 1),
21 | MonthDay.of(JANUARY, 6),
22 | MonthDay.of(MAY, 1),
23 | MonthDay.of(MAY, 3),
24 | MonthDay.of(AUGUST, 15),
25 | MonthDay.of(NOVEMBER, 1),
26 | MonthDay.of(NOVEMBER, 11),
27 | MonthDay.of(DECEMBER, 25),
28 | MonthDay.of(DECEMBER, 26)
29 | );
30 |
31 | public boolean isHoliday(LocalDate date) {
32 | return isWeekend(date) ||
33 | isFixedHoliday(date) ||
34 | isEasterMonday(date) ||
35 | isCorpusChristi(date);
36 | }
37 |
38 | private boolean isWeekend(LocalDate date) {
39 | return date.getDayOfWeek() == DayOfWeek.SATURDAY ||
40 | date.getDayOfWeek() == DayOfWeek.SUNDAY;
41 | }
42 |
43 | private boolean isFixedHoliday(LocalDate date) {
44 | return FIXED_HOLIDAYS.contains(MonthDay.from(date));
45 | }
46 |
47 | private boolean isEasterMonday(LocalDate date) {
48 | LocalDate easterThatYear = Easter.sundayFor(Year.of(date.getYear()));
49 | return date.equals(easterThatYear.plusDays(1));
50 | }
51 |
52 | private boolean isCorpusChristi(LocalDate date) {
53 | LocalDate easterThatYear = Easter.sundayFor(Year.of(date.getYear()));
54 | return date.equals(easterThatYear.plusDays(60));
55 | }
56 |
57 | @Override
58 | public boolean isWorkingDay(LocalDate date) {
59 | return !isHoliday(date);
60 | }
61 |
62 | @Override
63 | public LocalDate nextHolidayAfter(LocalDate date) {
64 | LocalDate cur = date;
65 | do {
66 | cur = cur.plusDays(1);
67 | } while(isWorkingDay(cur));
68 | return cur;
69 | }
70 |
71 | @Override
72 | public LocalDate nextWorkingDayAfter(LocalDate date) {
73 | LocalDate cur = date;
74 | do {
75 | cur = cur.plusDays(1);
76 | } while(isHoliday(cur));
77 | return cur;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/interfaces/Encrypter.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.interfaces;
2 |
3 | import java.io.IOException;
4 | import java.io.InputStream;
5 | import java.io.Reader;
6 | import java.nio.charset.Charset;
7 |
8 | public interface Encrypter {
9 | byte[] encode(byte[] bytes);
10 |
11 | byte[] encode(String str, Charset charset);
12 |
13 | byte[] encode(char[] chars, Charset charset);
14 |
15 | byte[] encode(Reader reader, Charset charset) throws IOException;
16 |
17 | byte[] encode(InputStream is) throws IOException;
18 | }
19 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/interfaces/ReverseEncrypter.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.interfaces;
2 |
3 | import org.apache.commons.io.IOUtils;
4 |
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.Reader;
8 | import java.nio.charset.Charset;
9 |
10 | public class ReverseEncrypter implements Encrypter {
11 |
12 | @Override
13 | public byte[] encode(byte[] bytes) {
14 | final byte[] result = new byte[bytes.length];
15 | for (int i = 0; i < bytes.length; ++i) {
16 | result[i] = (byte) (0xFF - bytes[i]);
17 | }
18 | return result;
19 | }
20 |
21 | @Override
22 | public byte[] encode(String str, Charset charset) {
23 | return encode(str.getBytes(charset));
24 | }
25 |
26 | @Override
27 | public byte[] encode(char[] chars, Charset charset) {
28 | return encode(String.valueOf(chars), charset);
29 | }
30 |
31 | @Override
32 | public byte[] encode(Reader reader, Charset charset) throws IOException {
33 | return encode(IOUtils.toByteArray(reader, charset));
34 | }
35 |
36 | @Override
37 | public byte[] encode(InputStream is) throws IOException {
38 | return encode(IOUtils.toByteArray(is));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/interfaces/RotEncrypter.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.interfaces;
2 |
3 | import org.apache.commons.io.IOUtils;
4 |
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.Reader;
8 | import java.nio.charset.Charset;
9 |
10 | public class RotEncrypter implements Encrypter {
11 |
12 | @Override
13 | public byte[] encode(byte[] bytes) {
14 | final byte[] result = new byte[bytes.length];
15 | for (int i = 0; i < bytes.length; ++i) {
16 | result[i] = (byte) (bytes[i] + 13);
17 | }
18 | return result;
19 | }
20 |
21 | @Override
22 | public byte[] encode(String str, Charset charset) {
23 | return encode(str.getBytes(charset));
24 | }
25 |
26 | @Override
27 | public byte[] encode(char[] chars, Charset charset) {
28 | return encode(String.valueOf(chars), charset);
29 | }
30 |
31 | @Override
32 | public byte[] encode(Reader reader, Charset charset) throws IOException {
33 | return encode(IOUtils.toByteArray(reader, charset));
34 | }
35 |
36 | @Override
37 | public byte[] encode(InputStream is) throws IOException {
38 | return encode(IOUtils.toByteArray(is));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/interfaces/XorEncrypter.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.interfaces;
2 |
3 | import org.apache.commons.io.IOUtils;
4 |
5 | import java.io.IOException;
6 | import java.io.InputStream;
7 | import java.io.Reader;
8 | import java.nio.charset.Charset;
9 |
10 | public class XorEncrypter implements Encrypter {
11 |
12 | @Override
13 | public byte[] encode(byte[] bytes) {
14 | final byte[] result = new byte[bytes.length];
15 | for (int i = 0; i < bytes.length; ++i) {
16 | result[i] = (byte) (bytes[i] ^ 0xCC);
17 | }
18 | return result;
19 | }
20 |
21 | @Override
22 | public byte[] encode(String str, Charset charset) {
23 | return encode(str.getBytes(charset));
24 | }
25 |
26 | @Override
27 | public byte[] encode(char[] chars, Charset charset) {
28 | return encode(String.valueOf(chars), charset);
29 | }
30 |
31 | @Override
32 | public byte[] encode(Reader reader, Charset charset) throws IOException {
33 | return encode(IOUtils.toByteArray(reader, charset));
34 | }
35 |
36 | @Override
37 | public byte[] encode(InputStream is) throws IOException {
38 | return encode(IOUtils.toByteArray(is));
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/people/Person.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.people;
2 |
3 | import java.time.LocalDate;
4 | import java.util.Arrays;
5 | import java.util.HashSet;
6 | import java.util.Set;
7 |
8 | public class Person {
9 |
10 | private final String name;
11 | private final Sex sex;
12 | private final int weight;
13 | private final int height;
14 | private final LocalDate dateOfBirth;
15 | private final Set phoneNumbers;
16 |
17 | public Person(String name, Sex sex, int weight, int height, LocalDate dateOfBirth, Phone... phoneNumbers) {
18 | this.name = name;
19 | this.sex = sex;
20 | this.weight = weight;
21 | this.height = height;
22 | this.dateOfBirth = dateOfBirth;
23 | this.phoneNumbers = new HashSet<>(Arrays.asList(phoneNumbers));
24 | }
25 |
26 | public String getName() {
27 | return name;
28 | }
29 |
30 | public int getHeight() {
31 | return height;
32 | }
33 |
34 | public LocalDate getDateOfBirth() {
35 | return dateOfBirth;
36 | }
37 |
38 | public Sex getSex() {
39 | return sex;
40 | }
41 |
42 | public int getWeight() {
43 | return weight;
44 | }
45 |
46 | public Set getPhoneNumbers() {
47 | return phoneNumbers;
48 | }
49 |
50 | @Override
51 | public String toString() {
52 | return "Person{name='" + name + '\'' + ", sex=" + sex + ", weight=" + weight + ", height=" + height + ", dateOfBirth=" + dateOfBirth + '}';
53 | }
54 |
55 | @Override
56 | public boolean equals(Object o) {
57 | if (this == o) return true;
58 | if (o == null || getClass() != o.getClass()) return false;
59 |
60 | Person person = (Person) o;
61 | return height == person.height
62 | && weight == person.weight
63 | && dateOfBirth.equals(person.dateOfBirth)
64 | && name.equals(person.name)
65 | && phoneNumbers.equals(person.phoneNumbers)
66 | && sex == person.sex;
67 | }
68 |
69 | @Override
70 | public int hashCode() {
71 | int result = name.hashCode();
72 | result = 31 * result + sex.hashCode();
73 | result = 31 * result + weight;
74 | result = 31 * result + height;
75 | result = 31 * result + dateOfBirth.hashCode();
76 | result = 31 * result + phoneNumbers.hashCode();
77 | return result;
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/people/PersonDao.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.people;
2 |
3 |
4 | import java.io.BufferedReader;
5 | import java.io.IOException;
6 | import java.io.InputStreamReader;
7 | import java.nio.charset.StandardCharsets;
8 | import java.time.LocalDate;
9 | import java.util.List;
10 |
11 | /**
12 | * Loads people from file. Skips header and entries without name
13 | */
14 | public class PersonDao {
15 |
16 | public List loadPeopleDatabase() {
17 | try (BufferedReader bufferedReader = open("/people.csv")) {
18 | throw new UnsupportedOperationException("loadPeopleDatabase()");
19 | // return bufferedReader.lines().
20 | } catch (IOException e) {
21 | throw new RuntimeException(e);
22 | }
23 | }
24 |
25 | private BufferedReader open(String fileName) {
26 | return new BufferedReader(
27 | new InputStreamReader(
28 | getClass().getResourceAsStream(fileName),
29 | StandardCharsets.UTF_8));
30 | }
31 |
32 | private Person parsePerson(String line) {
33 | final String[] columns = line.split(",");
34 | return new Person(
35 | columns[0],
36 | Sex.valueOf(columns[1]),
37 | Integer.parseInt(columns[3]),
38 | Integer.parseInt(columns[2]),
39 | LocalDate.of(
40 | Integer.parseInt(columns[6]),
41 | Integer.parseInt(columns[5]),
42 | Integer.parseInt(columns[4])
43 | )
44 | );
45 | }
46 |
47 |
48 | }
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/people/PersonService.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.people;
2 |
3 | import java.util.List;
4 | import java.util.concurrent.CompletableFuture;
5 | import java.util.concurrent.ExecutorService;
6 | import java.util.concurrent.Executors;
7 |
8 | public class PersonService implements AutoCloseable {
9 |
10 | private final ExecutorService pool = Executors.newFixedThreadPool(8);
11 | private final PersonDao dao = new PersonDao();
12 |
13 | public CompletableFuture> loadPeople() {
14 | return CompletableFuture.supplyAsync(dao::loadPeopleDatabase, pool);
15 | }
16 |
17 | public CompletableFuture loadPerson(String name) {
18 | throw new UnsupportedOperationException("Not yet implemented");
19 | }
20 |
21 | public CompletableFuture calculateRisk(Person person) {
22 | return CompletableFuture.supplyAsync(() -> person.getHeight() / 200.0, pool);
23 | }
24 |
25 | public double bodyMassIndex(Person person) {
26 | return person.getWeight() / (person.getHeight() / 100.0 * person.getHeight() / 100.0);
27 | }
28 |
29 | public CompletableFuture nextUniqueId() {
30 | return CompletableFuture.supplyAsync(() -> 42, pool);
31 | }
32 |
33 |
34 | @Override
35 | public void close() throws Exception {
36 | pool.shutdownNow();
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/people/Phone.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.people;
2 |
3 | public class Phone {
4 |
5 | private final int countryCode;
6 | private final long number;
7 |
8 | public Phone(int countryCode, long number) {
9 | this.countryCode = countryCode;
10 | this.number = number;
11 | }
12 |
13 | public int getCountryCode() {
14 | return countryCode;
15 | }
16 |
17 | public long getNumber() {
18 | return number;
19 | }
20 |
21 | @Override
22 | public String toString() {
23 | return "Phone{" + countryCode + " " + number + '}';
24 | }
25 |
26 | @Override
27 | public boolean equals(Object o) {
28 | if (this == o) return true;
29 | if (o == null || getClass() != o.getClass()) return false;
30 |
31 | Phone phone = (Phone) o;
32 | return countryCode == phone.countryCode && number == phone.number;
33 |
34 | }
35 |
36 | @Override
37 | public int hashCode() {
38 | int result = countryCode;
39 | result = 31 * result + (int) (number ^ (number >>> 32));
40 | return result;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/people/Sex.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.people;
2 |
3 | public enum Sex {
4 |
5 | MALE, FEMALE
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/stackoverflow/ArtificialSleepWrapper.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.stackoverflow;
2 |
3 | import org.jsoup.nodes.Document;
4 |
5 | import java.util.Random;
6 | import java.util.concurrent.TimeUnit;
7 |
8 | public class ArtificialSleepWrapper implements StackOverflowClient {
9 |
10 | private static final Random RANDOM = new Random();
11 |
12 | private final StackOverflowClient target;
13 |
14 | public ArtificialSleepWrapper(StackOverflowClient target) {
15 | this.target = target;
16 | }
17 |
18 | @Override
19 | public String mostRecentQuestionAbout(String tag) {
20 | final long start = System.currentTimeMillis();
21 | final String result = target.mostRecentQuestionAbout(tag);
22 | artificialSleep(1000 - (System.currentTimeMillis() - start));
23 | return result;
24 | }
25 |
26 | @Override
27 | public Document mostRecentQuestionsAbout(String tag) {
28 | artificialSleep(1000);
29 | final long start = System.currentTimeMillis();
30 | final Document result = target.mostRecentQuestionsAbout(tag);
31 | artificialSleep(1000 - (System.currentTimeMillis() - start));
32 | return result;
33 | }
34 |
35 | protected static void artificialSleep(long expected) {
36 | try {
37 | TimeUnit.MILLISECONDS.sleep((long) (expected + RANDOM.nextGaussian() * expected / 2));
38 | } catch (InterruptedException e) {
39 | throw new RuntimeException(e);
40 | }
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/stackoverflow/FallbackStubClient.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.stackoverflow;
2 |
3 | import com.google.common.base.Throwables;
4 | import org.apache.commons.io.IOUtils;
5 | import org.jsoup.Jsoup;
6 | import org.jsoup.nodes.Document;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.io.IOException;
11 |
12 | public class FallbackStubClient implements StackOverflowClient {
13 |
14 | private static final Logger log = LoggerFactory.getLogger(FallbackStubClient.class);
15 |
16 | private final StackOverflowClient target;
17 |
18 | public FallbackStubClient(StackOverflowClient target) {
19 | this.target = target;
20 | }
21 |
22 | @Override
23 | public String mostRecentQuestionAbout(String tag) {
24 | try {
25 | return target.mostRecentQuestionAbout(tag);
26 | } catch (Exception e) {
27 | log.warn("Problem retrieving tag {}", tag, e);
28 | switch(tag) {
29 | case "java":
30 | return "How to generate xml report with maven depencency?";
31 | case "scala":
32 | return "Update a timestamp SettingKey in an sbt 0.12 task";
33 | case "groovy":
34 | return "Reusing Grails variables inside Config.groovy";
35 | case "clojure":
36 | return "Merge two comma delimited strings in Clojure";
37 | default:
38 | throw e;
39 | }
40 | }
41 | }
42 |
43 | @Override
44 | public Document mostRecentQuestionsAbout(String tag) {
45 | try {
46 | return target.mostRecentQuestionsAbout(tag);
47 | } catch (Exception e) {
48 | log.warn("Problem retrieving recent question {}", tag, e);
49 | return loadStubHtmlFromDisk(tag);
50 | }
51 | }
52 |
53 | private Document loadStubHtmlFromDisk(String tag) {
54 | try {
55 | final String html = IOUtils.toString(getClass().getResource("/" + tag + "-question.html"));
56 | return Jsoup.parse(html);
57 | } catch (IOException e1) {
58 | throw Throwables.propagate(e1);
59 | }
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/stackoverflow/HttpStackOverflowClient.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.stackoverflow;
2 |
3 | import com.google.common.base.Throwables;
4 | import org.jsoup.Jsoup;
5 | import org.jsoup.nodes.Document;
6 |
7 | import java.io.IOException;
8 |
9 | public class HttpStackOverflowClient implements StackOverflowClient {
10 |
11 | @Override
12 | public String mostRecentQuestionAbout(String tag) {
13 | return fetchTitleOnline(tag);
14 | }
15 |
16 | @Override
17 | public Document mostRecentQuestionsAbout(String tag) {
18 | try {
19 | return Jsoup.
20 | connect("http://stackoverflow.com/questions/tagged/" + tag).
21 | get();
22 | } catch (IOException e) {
23 | throw Throwables.propagate(e);
24 | }
25 | }
26 |
27 | private String fetchTitleOnline(String tag) {
28 | return mostRecentQuestionsAbout(tag).select("a.question-hyperlink").get(0).text();
29 | }
30 |
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/stackoverflow/InjectErrorsWrapper.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.stackoverflow;
2 |
3 | import org.jsoup.nodes.Document;
4 | import org.slf4j.Logger;
5 | import org.slf4j.LoggerFactory;
6 |
7 | import java.util.Arrays;
8 | import java.util.HashSet;
9 | import java.util.Set;
10 |
11 | public class InjectErrorsWrapper implements StackOverflowClient {
12 |
13 | private static final Logger log = LoggerFactory.getLogger(InjectErrorsWrapper.class);
14 |
15 | private final StackOverflowClient target;
16 | private final Set blackList;
17 |
18 | public InjectErrorsWrapper(StackOverflowClient target, String... blackList) {
19 | this.target = target;
20 | this.blackList = new HashSet<>(Arrays.asList(blackList));
21 | }
22 |
23 | @Override
24 | public String mostRecentQuestionAbout(String tag) {
25 | throwIfBlackListed(tag);
26 | return target.mostRecentQuestionAbout(tag);
27 | }
28 |
29 | @Override
30 | public Document mostRecentQuestionsAbout(String tag) {
31 | throwIfBlackListed(tag);
32 | return target.mostRecentQuestionsAbout(tag);
33 | }
34 |
35 | private void throwIfBlackListed(String tag) {
36 | if (blackList.contains(tag)) {
37 | ArtificialSleepWrapper.artificialSleep(400);
38 | log.warn("About to throw artifical exception due to: {}", tag);
39 | throw new IllegalArgumentException("Unsupported " + tag);
40 | }
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/stackoverflow/LoadFromStackOverflowTask.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.stackoverflow;
2 |
3 | import org.slf4j.Logger;
4 | import org.slf4j.LoggerFactory;
5 |
6 | import java.util.concurrent.Callable;
7 |
8 | public class LoadFromStackOverflowTask implements Callable {
9 |
10 | private static final Logger log = LoggerFactory.getLogger(LoadFromStackOverflowTask.class);
11 |
12 | private final StackOverflowClient client;
13 | private final String tag;
14 |
15 | public LoadFromStackOverflowTask(StackOverflowClient client, String tag) {
16 | this.client = client;
17 | this.tag = tag;
18 | }
19 |
20 | @Override
21 | public String call() throws Exception {
22 | return client.mostRecentQuestionAbout(tag);
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/stackoverflow/LoggingWrapper.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.stackoverflow;
2 |
3 | import com.google.common.base.Joiner;
4 | import com.google.common.base.Splitter;
5 | import com.google.common.collect.Iterables;
6 | import org.jsoup.nodes.Document;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | public class LoggingWrapper implements StackOverflowClient {
11 |
12 | private static final Logger log = LoggerFactory.getLogger(LoggingWrapper.class);
13 |
14 | private final StackOverflowClient target;
15 |
16 | public LoggingWrapper(StackOverflowClient target) {
17 | this.target = target;
18 | }
19 |
20 | @Override
21 | public String mostRecentQuestionAbout(String tag) {
22 | log.debug("Entering mostRecentQuestionAbout({})", tag);
23 | final String title = target.mostRecentQuestionAbout(tag);
24 | log.debug("Leaving mostRecentQuestionAbout({}): {}", tag, title);
25 | return title;
26 | }
27 |
28 | @Override
29 | public Document mostRecentQuestionsAbout(String tag) {
30 | log.debug("Entering mostRecentQuestionsAbout({})", tag);
31 | final Document document = target.mostRecentQuestionsAbout(tag);
32 | if (log.isTraceEnabled()) {
33 | log.trace("Leaving mostRecentQuestionsAbout({}): {}", tag, htmlExcerpt(document));
34 | }
35 | return document;
36 | }
37 |
38 | private String htmlExcerpt(Document document) {
39 | final String outerHtml = document.outerHtml();
40 | final Iterable lines = Splitter.onPattern("\r?\n").split(outerHtml);
41 | final Iterable firstLines = Iterables.limit(lines, 4);
42 | final String excerpt = Joiner.on(' ').join(firstLines);
43 | final int remainingBytes = Math.max(outerHtml.length() - excerpt.length(), 0);
44 | return excerpt + " [...and " + remainingBytes + " chars]";
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/stackoverflow/Question.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.stackoverflow;
2 |
3 | public class Question {
4 | }
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/stackoverflow/StackOverflowClient.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.stackoverflow;
2 |
3 | import org.jsoup.nodes.Document;
4 |
5 | public interface StackOverflowClient {
6 |
7 | String mostRecentQuestionAbout(String tag);
8 | Document mostRecentQuestionsAbout(String tag);
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/util/LoremIpsum.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.util;
2 |
3 | import com.google.common.base.Splitter;
4 | import org.apache.commons.io.IOUtils;
5 |
6 | import java.io.IOException;
7 | import java.util.List;
8 | import java.util.Map;
9 | import java.util.function.BiFunction;
10 | import java.util.function.Function;
11 | import java.util.stream.Collectors;
12 |
13 | import static com.google.common.base.CharMatcher.anyOf;
14 |
15 | /**
16 | * @see Map#merge(Object, Object, BiFunction)
17 | * @see Map#computeIfAbsent(Object, Function)
18 | * @see Collectors#groupingBy(Function)
19 | */
20 | public class LoremIpsum {
21 |
22 | public static String text() throws IOException {
23 | return IOUtils.toString(LoremIpsum.class.getResourceAsStream("/lorem-ipsum.txt"));
24 | }
25 |
26 | /**
27 | * Case insensitive
28 | */
29 | public static Map wordCount(String text) {
30 | throw new UnsupportedOperationException("wordCount()");
31 | }
32 |
33 | private static List splitWords(String text) {
34 | return Splitter
35 | .on(anyOf(" .,\n"))
36 | .trimResults()
37 | .omitEmptyStrings()
38 | .splitToList(text);
39 | }
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/java8/util/PrimeUtil.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8.util;
2 |
3 | import java.util.function.LongUnaryOperator;
4 | import java.util.stream.LongStream;
5 |
6 | public class PrimeUtil {
7 |
8 | /**
9 | * TODO: Try to implement this without loops and if's
10 | * @see LongStream#iterate(long, LongUnaryOperator)
11 | */
12 | public static long nextPrimeAfter(long x) {
13 | throw new UnsupportedOperationException("nextPrimeAfter()");
14 | }
15 |
16 | /**
17 | * TODO: Try to implement this without loops and if's
18 | * @see LongStream#range(long, long)
19 | */
20 | public static boolean isPrime(long x) {
21 | throw new UnsupportedOperationException("isPrime()");
22 | }
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/rxjava/ObservableOps.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.rxjava;
2 |
3 | import com.nurkiewicz.rxjava.util.Indexed;
4 | import rx.Observable;
5 |
6 | import java.util.List;
7 | import java.util.concurrent.CompletableFuture;
8 | import java.util.function.UnaryOperator;
9 |
10 | public class ObservableOps {
11 |
12 | public static Observable toObservable(CompletableFuture future) {
13 | throw new UnsupportedOperationException("toObservable()");
14 | }
15 |
16 | /**
17 | * Non-blocking
18 | */
19 | public static CompletableFuture> toCompletableFuture(Observable observable) {
20 | throw new UnsupportedOperationException("toCompletableFuture()");
21 | }
22 |
23 | public static Observable iterate(T initialValue, UnaryOperator nextFun) {
24 | throw new UnsupportedOperationException("iterate()");
25 | }
26 |
27 | public static Observable naturals() {
28 | throw new UnsupportedOperationException("naturals()");
29 | }
30 |
31 | public static Observable> index(Observable input) {
32 | throw new UnsupportedOperationException("index()");
33 | }
34 |
35 | public static Observable.Operator, T> withIndex() {
36 | throw new UnsupportedOperationException("withIndex()");
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/nurkiewicz/rxjava/util/Indexed.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.rxjava.util;
2 |
3 | public class Indexed {
4 |
5 | private final T value;
6 | private final int index;
7 |
8 | public Indexed(T value, int index) {
9 | this.value = value;
10 | this.index = index;
11 | }
12 |
13 | public T getValue() {
14 | return value;
15 | }
16 |
17 | public int getIndex() {
18 | return index;
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/resources/lorem-ipsum.txt:
--------------------------------------------------------------------------------
1 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam sollicitudin mattis enim. Maecenas tincidunt, leo vitae interdum suscipit, tortor sem faucibus elit, eget rhoncus mauris nulla in enim. Etiam volutpat velit non ligula consequat porta id non odio. Maecenas id nisi et leo tempor aliquet vitae eget quam. Sed a pulvinar turpis. Integer non lacinia dui. Integer aliquet vulputate tortor, eget mollis justo tristique et. Nunc ac tincidunt massa. Maecenas malesuada pharetra vestibulum. Suspendisse vestibulum nisl enim, eget adipiscing massa suscipit aliquet. Integer sit amet lectus blandit, auctor sem blandit, sollicitudin nulla. Suspendisse porta risus eget turpis pretium pulvinar.
2 | In convallis aliquet nibh, et rutrum erat molestie nec. Sed fermentum mattis dolor, eget ullamcorper massa mattis quis. Nullam rutrum tortor vel quam vestibulum, non imperdiet nisl rhoncus. Curabitur posuere massa sit amet scelerisque malesuada. Aenean imperdiet consectetur dui in malesuada. Curabitur nec tincidunt erat. Nam accumsan quis tellus a egestas. Nulla ligula leo, luctus eget sagittis ac, varius a dolor.
3 | In rhoncus magna turpis, et aliquet elit facilisis sit amet. Integer suscipit turpis a nulla imperdiet fermentum. In ultricies quis eros mattis feugiat. Integer vehicula, quam eu semper mattis, nunc augue placerat tortor, sed congue purus metus non turpis. Morbi congue tristique nunc at lacinia. Nullam euismod, lacus non pellentesque iaculis, quam augue dapibus nunc, et condimentum enim magna quis mauris. Mauris imperdiet tellus in dictum aliquet. Mauris congue dolor ut mollis convallis. Integer id consectetur orci. Etiam sed blandit erat. Donec pellentesque augue ac mi sagittis, non accumsan magna viverra. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Proin lobortis, tortor nec euismod fermentum, nibh ipsum faucibus mauris, ac viverra metus lectus a ipsum. Ut laoreet lectus et nibh sagittis, quis pellentesque quam pellentesque. Mauris nec sem interdum, congue lectus quis, convallis sapien.
4 | Ut vel auctor metus. Duis at enim est. Nulla facilisi. Praesent placerat ligula id nibh fermentum vehicula. Praesent at nibh non enim placerat blandit. Cras eleifend sit amet neque ut cursus. Aenean ac purus mattis mi sollicitudin venenatis eu vehicula felis. Maecenas est velit, elementum sed vulputate nec, feugiat sit amet quam. Cras suscipit luctus ornare. Praesent tristique euismod lectus, eget auctor augue volutpat a. Sed consequat mauris eu massa porta elementum.
5 | Nunc id sem porttitor, adipiscing tellus eget, vestibulum metus. Phasellus sit amet placerat erat. Ut congue metus eget est lobortis adipiscing. Vivamus pharetra nisi id augue bibendum cursus sed eget sapien. Nulla ullamcorper nisi tortor, sit amet semper massa fermentum sed. Nulla eu nisi venenatis, fringilla lacus eget, tincidunt elit. Fusce tristique congue ligula vitae consectetur. Aenean pellentesque venenatis quam eu ornare. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
--------------------------------------------------------------------------------
/src/main/resources/people.csv:
--------------------------------------------------------------------------------
1 | #Name,Sex,Height,Weight,BirthDay,Month,Year
2 | Viktoria,FEMALE,174,63,27,8,1986
3 | William,MALE,180,64,26,5,1988
4 | Sofija,FEMALE,169,59,6,5,1984
5 | Onni,MALE,169,48,2,12,1975
6 | Charlie,MALE,179,67,5,8,1976
7 | Mia,FEMALE,185,85,19,4,1983
8 | Sofiya,FEMALE,175,70,20,12,1994
9 | Dylan,MALE,186,72,28,10,1971
10 | Sofia,FEMALE,166,63,23,2,1971
11 | Marie,FEMALE,165,62,19,12,1970
12 | Sofiya,FEMALE,170,66,1,2,1985
13 | Jacob,MALE,167,55,22,6,1963
14 | Luca,MALE,183,80,21,8,1970
15 | Lara,FEMALE,167,55,9,4,1963
16 | Nora,FEMALE,169,54,14,7,1961
17 | Jakub,MALE,174,57,13,6,1987
18 | Georgi,MALE,184,84,21,6,1967
19 | Noah,MALE,180,68,23,1,1977
20 | Nikola,MALE,175,64,15,6,1972
21 | Nareh,FEMALE,167,55,26,10,1981
22 | Lukas,MALE,182,76,25,9,1998
23 | Léa,FEMALE,164,61,9,11,1969
24 | Aron,MALE,183,73,11,12,1971
25 | Noah,MALE,191,83,15,7,1969
26 | Luka,MALE,182,69,12,2,1971
27 | Georgios,MALE,183,73,16,6,1978
28 | Emma,FEMALE,179,60,13,11,1973
29 | Nathan,MALE,174,69,2,1,1970
30 | Daniyar,MALE,183,77,4,6,1976
31 | Sophie,FEMALE,166,60,18,1,1972
32 | Lucas,MALE,168,67,12,5,1985
33 | Francesco,MALE,183,70,25,9,1972
34 | Jack,MALE,180,81,15,6,1970
35 | Yusif,MALE,182,69,7,8,1992
36 | Davit,MALE,185,71,5,11,1982
37 | Rodrigo,MALE,176,52,10,1,1981
38 | Emma,FEMALE,174,60,24,7,1980
39 | Isabella,FEMALE,173,71,1,1,1983
40 | Chloé,FEMALE,178,66,10,4,1976
41 | Alexander,MALE,177,68,24,5,1987
42 | Marija,FEMALE,173,68,17,10,1968
43 | Luka,MALE,167,72,6,5,1992
44 | Harry,MALE,175,64,19,9,1991
45 | Luca,MALE,181,65,24,9,1965
46 | Alexandra,FEMALE,166,52,14,12,1988
47 | Amelia,FEMALE,168,62,8,10,1979
48 | Emma,FEMALE,162,65,7,3,1975
49 | Giorgi,MALE,184,60,15,7,1976
50 | Rasmus,MALE,181,72,15,3,1980
51 | Ellen,FEMALE,176,71,1,12,1966
52 | Sara,FEMALE,168,59,12,6,1978
53 | Uendi,FEMALE,170,66,22,12,1965
54 | Sevinj,FEMALE,183,92,1,11,1978
55 | Chloe,FEMALE,169,59,26,11,1986
56 | Ben,MALE,167,69,23,3,1963
57 | Nino,FEMALE,171,64,21,7,1979
58 | Matthew,MALE,159,55,8,12,1991
59 | Leandro,MALE,177,65,27,7,1985
60 | Jónas,MALE,178,69,16,8,1973
61 | Anna,FEMALE,182,76,9,4,1978
62 | Emilía,FEMALE,179,64,10,8,1972
63 | ,FEMALE,179,64,10,8,1972
64 | Maxim,MALE,177,65,11,5,1986
65 | Sarah,FEMALE,163,66,3,6,1972
66 | Emily,FEMALE,172,73,6,10,1964
67 | Alice,FEMALE,166,52,27,7,1995
68 | Lucía,FEMALE,176,77,19,10,1965
69 | Maria,FEMALE,173,62,18,4,1981
70 | Ivaana,FEMALE,177,62,12,11,1966
71 | Emma,FEMALE,169,54,1,11,1971
72 | Artyom,MALE,176,65,8,2,1966
73 | Maxim,MALE,177,68,17,9,1980
74 | Eliška,FEMALE,169,57,2,3,1994
75 | Sofia,FEMALE,167,50,2,8,1981
76 | Ben,MALE,171,73,15,12,1971
77 | Maria,FEMALE,161,57,12,6,1958
78 | Emma,FEMALE,166,46,13,9,1975
79 | Nathan,MALE,181,72,26,4,1964
80 | Luka,MALE,170,69,15,2,1976
81 | Matas,MALE,182,76,23,7,1976
82 | Markel,MALE,188,77,11,2,1961
83 | Mohamed,MALE,167,55,3,10,1968
84 | Anna,FEMALE,174,69,8,2,1978
85 | Lina,FEMALE,172,62,3,4,1972
86 | Anastasia,FEMALE,162,57,15,10,1974
87 | Daan,MALE,169,59,12,4,1962
88 | Luka,MALE,171,64,14,8,1962
89 | Emma,FEMALE,174,60,8,10,1972
90 | Maria,FEMALE,168,50,28,6,1978
91 | Lamija,FEMALE,163,58,11,10,1992
92 | Anastasia,FEMALE,162,62,11,6,1980
93 | Daniel,MALE,183,80,7,12,1982
94 | Jack,MALE,177,68,2,3,1986
95 | Alexander,MALE,184,84,23,10,1986
96 | Jakub,MALE,173,71,15,2,1985
97 | Emil,MALE,163,55,12,7,1971
98 | Gabriel,MALE,182,72,27,6,1979
99 | Jakub,MALE,184,71,11,11,1981
100 | Andrei,MALE,179,73,2,10,1976
101 | Lara,FEMALE,156,53,26,10,1990
102 | Lucas,MALE,181,62,1,8,1962
103 | Sofia,FEMALE,181,72,9,10,1968
104 | Milan,MALE,186,69,9,2,1946
105 | Lena,FEMALE,164,61,14,1,1975
106 | Alina,FEMALE,168,67,17,9,1972
107 | Annalena,FEMALE,175,61,21,2,1972
108 | Noel,MALE,199,83,27,10,1974
109 | Anna,FEMALE,167,61,4,10,1972
110 | Mathéo,MALE,180,64,22,9,1966
111 | Malik,MALE,175,67,6,8,1967
112 | Gabriel,MALE,175,58,7,8,1977
113 | Léa,FEMALE,163,55,11,6,1968
114 | Artem,MALE,186,76,4,11,1974
115 | ,MALE,186,76,4,11,1974
116 | Victor,MALE,179,73,25,3,1975
117 | Amelia,FEMALE,166,57,16,5,1961
118 | Ane,FEMALE,173,59,14,6,1957
119 | Zahra,FEMALE,167,61,19,4,1979
120 | Sophie,FEMALE,160,51,24,5,1980
121 | Aleksandar,MALE,179,73,6,2,1966
122 | Mia,FEMALE,159,60,25,5,1965
123 | Julia,FEMALE,169,54,25,6,1972
124 | Maria,FEMALE,166,63,1,12,1971
125 | Ali,MALE,177,59,23,3,1974
126 | Julia,FEMALE,173,59,18,4,1978
127 | Emilija,FEMALE,174,75,15,12,1993
128 | Amar,MALE,183,83,20,8,1967
129 | Yanis,MALE,178,82,3,11,1957
130 | Emma,FEMALE,168,59,24,2,1977
131 | Marc,MALE,185,82,10,4,1975
132 | Sofia,FEMALE,169,62,12,2,1953
133 | Lucija,FEMALE,166,66,2,11,1970
134 | Hanna,FEMALE,168,62,26,7,1967
135 | Roberts,MALE,183,66,24,7,1986
136 | Eliza,FEMALE,168,62,15,7,1968
137 | James,MALE,177,75,9,4,1969
138 | Ella,FEMALE,168,59,13,1,1980
139 | Bence,MALE,178,72,28,3,1981
140 | Jack,MALE,177,68,5,6,1989
141 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J01_HelloWorldTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import org.junit.Test;
4 |
5 | import java.util.Arrays;
6 | import java.util.List;
7 |
8 | import static java.util.stream.Collectors.toList;
9 | import static org.fest.assertions.api.Assertions.assertThat;
10 |
11 | /**
12 | * - Smoke test, make sure it compiles, runs and passes.
13 | */
14 | public class J01_HelloWorldTest {
15 |
16 | @Test
17 | public void hello() {
18 | final List input = Arrays.asList(2, 3, 5, 7, 11);
19 |
20 | final List output = input.
21 | stream().
22 | map(i -> i * 2).
23 | collect(toList());
24 |
25 | assertThat(output).containsExactly(4, 6, 10, 14, 22);
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J02_InterfacesTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.interfaces.Encrypter;
4 | import com.nurkiewicz.java8.interfaces.ReverseEncrypter;
5 | import com.nurkiewicz.java8.interfaces.RotEncrypter;
6 | import com.nurkiewicz.java8.interfaces.XorEncrypter;
7 | import junitparams.JUnitParamsRunner;
8 | import junitparams.Parameters;
9 | import org.junit.Test;
10 | import org.junit.runner.RunWith;
11 |
12 | import java.io.ByteArrayInputStream;
13 | import java.io.IOException;
14 | import java.io.StringReader;
15 |
16 | import static java.nio.charset.StandardCharsets.UTF_8;
17 | import static junitparams.JUnitParamsRunner.$;
18 | import static org.fest.assertions.api.Assertions.assertThat;
19 |
20 | /**
21 | * - Improve encrypter to use default methods to avoid code duplication.
22 | */
23 | @RunWith(JUnitParamsRunner.class)
24 | public class J02_InterfacesTest {
25 |
26 | @Test
27 | @Parameters
28 | public void testAllMethods(Encrypter encrypter, byte[] expected) throws IOException {
29 | final byte[] input = new byte[]{90, 100, 110};
30 | final char[] charInput = new char[]{'Z', 'd', 'n'};
31 |
32 | assertThat(encrypter.encode(input)).isEqualTo(expected);
33 | assertThat(encrypter.encode(new String(input), UTF_8)).isEqualTo(expected);
34 | assertThat(encrypter.encode(charInput, UTF_8)).isEqualTo(expected);
35 | assertThat(encrypter.encode(new StringReader(new String(charInput)), UTF_8)).isEqualTo(expected);
36 | assertThat(encrypter.encode(new ByteArrayInputStream(input))).isEqualTo(expected);
37 | }
38 |
39 | private Object[] parametersForTestAllMethods() {
40 | return $(
41 | $(new ReverseEncrypter(), new byte[]{-91, -101, -111}),
42 | $(new RotEncrypter(), new byte[]{103, 113, 123}),
43 | $(new XorEncrypter(), new byte[]{-106, -88, -94})
44 | );
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J02b_ConflictingDefaultMethodsTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.defmethods.Engine;
4 | import com.nurkiewicz.java8.defmethods.Job;
5 | import com.nurkiewicz.java8.defmethods.Lifecycle;
6 | import com.nurkiewicz.java8.defmethods.RuleEngine;
7 | import org.junit.Ignore;
8 | import org.junit.Test;
9 |
10 | import static org.fest.assertions.api.Assertions.assertThat;
11 |
12 | /**
13 | * Conflicting default methods
14 | * First let {@link RuleEngine} implement all three interfaces.
15 | * Then decide which of the conflicting implementations should be chosen.
16 | */
17 | @Ignore
18 | public class J02b_ConflictingDefaultMethodsTest {
19 |
20 | private final RuleEngine ruleEngine = new RuleEngine();
21 |
22 | @Test
23 | public void shouldExtendFewInterfaces() {
24 | assertThat(ruleEngine).isInstanceOf(Job.class);
25 | assertThat(ruleEngine).isInstanceOf(Engine.class);
26 | assertThat(ruleEngine).isInstanceOf(Lifecycle.class);
27 | }
28 |
29 | @Test
30 | public void shouldReturnValueFromJob() {
31 | assertThat(ruleEngine.start()).isEqualTo("Job");
32 | }
33 |
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J03_FunctionTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import org.junit.Ignore;
4 | import org.junit.Test;
5 | import org.mockito.InOrder;
6 |
7 | import java.util.Date;
8 | import java.util.function.Consumer;
9 | import java.util.function.Function;
10 | import java.util.function.LongConsumer;
11 | import java.util.function.Predicate;
12 | import java.util.function.Supplier;
13 |
14 | import static org.fest.assertions.api.Assertions.assertThat;
15 | import static org.fest.assertions.data.Offset.offset;
16 | import static org.mockito.Mockito.inOrder;
17 | import static org.mockito.Mockito.mock;
18 |
19 | /**
20 | * - Use explicit Function, Predicate, Supplier, Consumer (like Guava)
21 | * - Higher order functions - returning lambdas
22 | * - Change Encrypter to class taking Function
23 | * - Turning Function, Supplier and Producer into lambda
24 | * - Method references (method, static method, constructor)
25 | */
26 | @Ignore
27 | public class J03_FunctionTest {
28 |
29 | @Test
30 | public void shouldPrependHello() {
31 | final Function fun = null;
32 |
33 | assertThat(fun.apply(42)).isEqualTo("Answer is 42");
34 | }
35 |
36 | @Test
37 | public void shouldProduceAnswer() {
38 | final Supplier answerFun = null;
39 |
40 | assertThat(answerFun.get()).isEqualTo(42);
41 | }
42 |
43 | @Test
44 | public void shouldDecideIfNegative() {
45 | final Predicate isNegative = null;
46 |
47 | assertThat(isNegative.test(3.0)).isFalse();
48 | assertThat(isNegative.test(0.0)).isFalse();
49 | assertThat(isNegative.test(-1.1)).isTrue();
50 | }
51 |
52 | @Test
53 | public void shouldCallOtherClassInConsumer() {
54 | final Date dateMock = mock(Date.class);
55 |
56 | final Consumer consumer = null;
57 |
58 | consumer.accept(1000L);
59 | consumer.accept(2000L);
60 |
61 | final InOrder order = inOrder(dateMock);
62 | order.verify(dateMock).setTime(1000L);
63 | order.verify(dateMock).setTime(2000L);
64 | }
65 |
66 | @Test
67 | public void shouldCallOtherClassInPrimitiveConsumer() {
68 | final Date dateMock = mock(Date.class);
69 |
70 | final LongConsumer consumer = null;
71 |
72 | consumer.accept(1000L);
73 | consumer.accept(2000L);
74 |
75 | final InOrder order = inOrder(dateMock);
76 | order.verify(dateMock).setTime(1000L);
77 | order.verify(dateMock).setTime(2000L);
78 | }
79 |
80 | @Test
81 | public void shouldInvokeReturnedLambdas() throws Exception {
82 | //given
83 | final Function strLenFun = createStringLenFunction();
84 | final Function tripleFun = multiplyFun(3.0);
85 | final String input = "abcd";
86 |
87 | //when
88 | final int strLen = strLenFun.apply(input);
89 | final double tripled = tripleFun.apply(4);
90 |
91 | //then
92 | assertThat(strLen).isEqualTo(4);
93 | assertThat(tripled).isEqualTo(4 * 3.0, offset(0.01));
94 | }
95 |
96 | @Test
97 | public void shouldComposeFunctionsInVariousWays() throws Exception {
98 | //given
99 | final Function strLenFun = createStringLenFunction();
100 | final Function tripleFun = multiplyFun(3.0);
101 | final Function andThenFun = strLenFun.andThen(tripleFun);
102 | final Function composeFun = tripleFun.compose(strLenFun);
103 | final String input = "abcd";
104 |
105 | //when
106 | final double naiveResult = tripleFun.apply(strLenFun.apply(input));
107 | final double andThenResult = andThenFun.apply(input);
108 | final double composeResult = composeFun.apply(input);
109 |
110 | //then
111 | assertThat(naiveResult).isEqualTo(4 * 3.0, offset(0.01));
112 | assertThat(andThenResult).isEqualTo(4 * 3.0, offset(0.01));
113 | assertThat(composeResult).isEqualTo(4 * 3.0, offset(0.01));
114 | }
115 |
116 | private Function multiplyFun(double times) {
117 | throw new UnsupportedOperationException("multiplyFun()");
118 | }
119 |
120 | private Function createStringLenFunction() {
121 | throw new UnsupportedOperationException("createStringLenFunction()");
122 | }
123 |
124 | }
125 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J04_FunctionalInterfacesTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import org.junit.Ignore;
4 | import org.junit.Test;
5 |
6 | import java.awt.event.ActionListener;
7 | import java.util.Comparator;
8 | import java.util.Date;
9 | import java.util.Random;
10 | import java.util.function.Supplier;
11 |
12 | import static org.fest.assertions.api.Assertions.assertThat;
13 | import static org.mockito.Mockito.mock;
14 | import static org.mockito.Mockito.verify;
15 |
16 | /**
17 | * What is a functional interface? @FunctionalInterface
18 | * Using lambdas instead of plain old Java classes (JButton)
19 | * - Implement functional interfaces using lambda syntax
20 | */
21 | @Ignore
22 | public class J04_FunctionalInterfacesTest {
23 |
24 | private final Random random = new Random();
25 |
26 | @Test
27 | public void testActionListenerLambda() {
28 | //given
29 | final Date dateMock = mock(Date.class);
30 | final ActionListener listener = null;
31 |
32 | //when
33 | listener.actionPerformed(null);
34 |
35 | //then
36 | verify(dateMock).setTime(1000L);
37 | }
38 |
39 | @Test
40 | public void testRunnableLambda() {
41 | //given
42 | final Date dateMock = mock(Date.class);
43 | Runnable block = null;
44 |
45 | //when
46 | block.run();
47 |
48 | //then
49 | verify(dateMock).setTime(1000L);
50 | }
51 |
52 | @Test
53 | public void testComparatorLambda() {
54 | final Comparator strLenComparator = null;
55 |
56 | assertThat(strLenComparator.compare("abc", "def")).isZero();
57 | assertThat(strLenComparator.compare("abc", "defg")).isLessThan(0);
58 | assertThat(strLenComparator.compare("abc", "de")).isGreaterThan(0);
59 | }
60 |
61 | @Test
62 | public void testCustomFunctionalInterface() {
63 | final RandomSource source = null;
64 |
65 | Supplier sourceSupplier = null;
66 |
67 | assertThat(source.oneOrMinusOne()).isIn(-1, 1);
68 | assertThat(sourceSupplier.get()).isIn(-1, 1);
69 | }
70 |
71 | }
72 |
73 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J05_MultiRunnerTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import org.junit.Ignore;
4 | import org.junit.Test;
5 |
6 | import java.util.Arrays;
7 | import java.util.Map;
8 | import java.util.concurrent.ConcurrentHashMap;
9 | import java.util.concurrent.atomic.LongAdder;
10 | import java.util.stream.IntStream;
11 |
12 | import static com.jayway.awaitility.Awaitility.await;
13 | import static com.jayway.awaitility.Awaitility.to;
14 | import static org.fest.assertions.api.Assertions.assertThat;
15 | import static org.hamcrest.CoreMatchers.is;
16 |
17 | /**
18 | * Implement simple utility methods for running blocks of code in multiple threads
19 | */
20 | @Ignore
21 | public class J05_MultiRunnerTest {
22 |
23 | @Test
24 | public void shouldExecuteTasksInMultipleThreads() throws Exception {
25 | //given
26 | final Map threads = new ConcurrentHashMap<>();
27 |
28 | //when
29 | IntStream.range(0, 100).forEach(i ->
30 | MultiRunner.runMultiThreaded(() -> {
31 | final Thread thread = Thread.currentThread();
32 | threads.put(thread.getId(), thread.getName());
33 | })
34 | );
35 |
36 | //then
37 | await().until(() -> threads.size() == MultiRunner.THREAD_COUNT);
38 | assertThat(threads).doesNotContainKey(Thread.currentThread().getId());
39 | }
40 |
41 | @Test
42 | public void shouldRunMultipleBlocks() throws Exception {
43 | //given
44 | final LongAdder counter = new LongAdder();
45 |
46 | //when
47 | MultiRunner.runMultiThreaded(Arrays.asList(
48 | () -> counter.add(1),
49 | () -> counter.add(2),
50 | () -> counter.add(3)
51 | ));
52 |
53 | //then
54 | await().untilCall(to(counter).sum(), is(1L + 2L + 3L));
55 | }
56 |
57 | @Test
58 | public void shouldRunTheSameTaskMultipleTimes() throws Exception {
59 | //given
60 | final LongAdder counter = new LongAdder();
61 |
62 | //when
63 | MultiRunner.runMultiThreaded(3, () -> counter.add(7));
64 |
65 | //then
66 | await().untilCall(to(counter).sum(), is(7L + 7L + 7L));
67 | }
68 |
69 | }
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J06_OptionalTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.people.Person;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 |
7 | import java.time.LocalDate;
8 | import java.time.Month;
9 | import java.util.Optional;
10 |
11 | import static com.nurkiewicz.java8.people.Sex.MALE;
12 | import static org.fest.assertions.api.Assertions.assertThat;
13 |
14 | /**
15 | * Transform old-fashioned code using nulls with Optional
16 | * Hint: use map/filter/flatMap/ifPresent
17 | */
18 | @Ignore
19 | public class J06_OptionalTest {
20 |
21 | private static final int PERSON_ID_WITH_NO_ADDRESS = 1;
22 | private static final int PERSON_ID_WITH_ADDRESS = 2;
23 | private static final int UNAVAILABLE_PERSON_ID = 0;
24 |
25 | private Person findPersonOrNull(int id) {
26 | switch(id) {
27 | case PERSON_ID_WITH_NO_ADDRESS:
28 | return new Person("James", MALE, 62, 169, LocalDate.of(2007, Month.DECEMBER, 21));
29 | case PERSON_ID_WITH_ADDRESS:
30 | return new Person("John", MALE, 62, 169, LocalDate.of(1985, Month.DECEMBER, 21));
31 | case UNAVAILABLE_PERSON_ID:
32 | return null;
33 | default:
34 | return null;
35 | }
36 | }
37 |
38 | private String lookupAddressOrNull(Person person) {
39 | if (person.getDateOfBirth().isAfter(LocalDate.of(2000, Month.JANUARY, 1))) {
40 | return "";
41 | }
42 | if (person.getDateOfBirth().isAfter(LocalDate.of(1980, Month.JANUARY, 1))) {
43 | return " Some St. ";
44 | }
45 | return null;
46 | }
47 |
48 | private String lookupAddressByIdOrNull(int id) {
49 | final Person personOrNull = findPersonOrNull(id);
50 | if (personOrNull != null) {
51 | if (personOrNull.getSex() == MALE) {
52 | final String addressOrNull = lookupAddressOrNull(personOrNull);
53 | if (addressOrNull != null && !addressOrNull.isEmpty()) {
54 | return addressOrNull.trim();
55 | } else {
56 | return null;
57 | }
58 | }
59 | }
60 | return null;
61 | }
62 |
63 | /**
64 | * Don't change, call from {@link #tryLookupAddressById(int)}
65 | */
66 | private Optional tryFindPerson(int id) {
67 | return Optional.ofNullable(findPersonOrNull(id));
68 | }
69 |
70 | /**
71 | * Don't change, call from {@link #tryLookupAddressById(int)}
72 | */
73 | private Optional tryLookupAddress(Person person) {
74 | return Optional.ofNullable(lookupAddressOrNull(person));
75 | }
76 |
77 | /**
78 | * TODO: Copy and refactor code from {@link #lookupAddressByIdOrNull}, but avoid nulls
79 | */
80 | private Optional tryLookupAddressById(int id) {
81 | return Optional.empty(); // tryFindPerson(id).
82 | }
83 |
84 | @Test
85 | public void nulls() {
86 | assertThat(lookupAddressByIdOrNull(UNAVAILABLE_PERSON_ID)).isNull();
87 | assertThat(lookupAddressByIdOrNull(PERSON_ID_WITH_NO_ADDRESS)).isNull();
88 | assertThat(lookupAddressByIdOrNull(PERSON_ID_WITH_ADDRESS)).isEqualTo("Some St.");
89 | }
90 |
91 | @Test
92 | public void optionals() {
93 | assertThat(tryLookupAddressById(UNAVAILABLE_PERSON_ID).isPresent()).isFalse();
94 | assertThat(tryLookupAddressById(PERSON_ID_WITH_NO_ADDRESS).isPresent()).isFalse();
95 | assertThat(tryLookupAddressById(PERSON_ID_WITH_ADDRESS).get()).isEqualTo("Some St.");
96 | }
97 |
98 | }
99 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J07_StreamsTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.people.Person;
4 | import com.nurkiewicz.java8.people.Phone;
5 | import org.junit.Ignore;
6 | import org.junit.Test;
7 |
8 | import java.time.LocalDate;
9 | import java.time.Month;
10 | import java.util.ArrayList;
11 | import java.util.Arrays;
12 | import java.util.Iterator;
13 | import java.util.List;
14 | import java.util.Optional;
15 | import java.util.function.Consumer;
16 |
17 | import static com.nurkiewicz.java8.people.Sex.FEMALE;
18 | import static com.nurkiewicz.java8.people.Sex.MALE;
19 | import static java.util.Collections.emptyList;
20 | import static java.util.stream.Collectors.toList;
21 | import static org.fest.assertions.api.Assertions.assertThat;
22 |
23 | /**
24 | * - What is Stream
25 | * - More complex operations on Stream, (map, filter, forEach, sorted)
26 | * - Only toList() Collector
27 | */
28 | @Ignore
29 | public class J07_StreamsTest {
30 |
31 | public static final List PEOPLE = Arrays.asList(
32 | new Person("Jane", FEMALE, 62, 169, LocalDate.of(1986, Month.DECEMBER, 21), new Phone(10, 555100200)),
33 | new Person("Bob", MALE, 71, 183, LocalDate.of(1982, Month.FEBRUARY, 5), new Phone(10, 555100201)),
34 | new Person("Steve", MALE, 85, 191, LocalDate.of(1980, Month.MAY, 4), new Phone(11, 555100200), new Phone(11, 555100201), new Phone(11, 555100202)),
35 | new Person("Alice", FEMALE, 54, 178, LocalDate.of(1984, Month.AUGUST, 17), new Phone(12, 555100202)),
36 | new Person("Eve", FEMALE, 61, 176, LocalDate.of(1987, Month.FEBRUARY, 9), new Phone(10, 555100200))
37 | );
38 |
39 | @Test
40 | public void doesAnyFemaleExist() {
41 | final boolean anyFemale = PEOPLE.
42 | stream().
43 | anyMatch(p -> p.getSex() == FEMALE);
44 |
45 | assertThat(anyFemale).isTrue();
46 | }
47 |
48 | @Test
49 | public void shouldReturnNamesSorted() {
50 | final List names = PEOPLE.
51 | stream().
52 | map(Person::getName).
53 | sorted().
54 | collect(toList());
55 |
56 | assertThat(names).containsExactly("Alice", "Bob", "Eve", "Jane", "Steve");
57 | }
58 |
59 | /**
60 | * Are all people below 80 kg?
61 | */
62 | @Test
63 | public void areAllPeopleSlim() {
64 | final boolean allSlim = true; // PEOPLE.stream().allMatch()
65 |
66 | assertThat(allSlim).isFalse();
67 | }
68 |
69 | /**
70 | * Are all people above 80 kg?
71 | */
72 | @Test
73 | public void areAllPeopleNotSlim() {
74 | final boolean allNotSlim = true;
75 |
76 | assertThat(allNotSlim).isFalse();
77 | }
78 |
79 | @Test
80 | public void findTallestPerson() {
81 | final Optional max = Optional.empty();
82 |
83 | assertThat(max.isPresent()).isTrue();
84 | assertThat(max.get()).isEqualTo(PEOPLE.get(2));
85 | }
86 |
87 | @Test
88 | public void countMales() {
89 | final long malesCount = 0;
90 |
91 | assertThat(malesCount).isEqualTo(2);
92 | }
93 |
94 | /**
95 | * Hint: use limit(2)
96 | */
97 | @Test
98 | public void twoOldestPeople() {
99 | final List oldest = emptyList();
100 |
101 | assertThat(oldest).containsExactly(PEOPLE.get(2), PEOPLE.get(1));
102 | }
103 |
104 | /**
105 | * Hint: PEOPLE.stream()...mapToInt()...sum()
106 | */
107 | @Test
108 | public void totalWeight() {
109 | final int totalWeight = 0;
110 |
111 | assertThat(totalWeight).isEqualTo(333);
112 | }
113 |
114 | @Test
115 | public void findUniqueCountryCodes() {
116 | final List distinctCountryCodes = emptyList(); // PEOPLE.stream()...flatMap()...distinct()
117 |
118 | assertThat(distinctCountryCodes).containsExactly(10, 11, 12);
119 | }
120 |
121 | /**
122 | * For each person born after LocalDate.of(1985, Month.DECEMBER, 25), add name to 'names'
123 | */
124 | @Test
125 | public void forEachYoungPerson() {
126 | List names = new ArrayList<>();
127 |
128 | // PEOPLE.stream()...forEach()
129 |
130 | assertThat(names).containsExactly("Jane", "Eve");
131 | }
132 |
133 | /**
134 | * @see Iterator#forEachRemaining(Consumer)
135 | */
136 | @Test
137 | public void shouldRunOverIterator() throws Exception {
138 | //given
139 | final Iterator iter = Arrays.asList(1, 2, 3).iterator();
140 | final StringBuilder sb = new StringBuilder();
141 |
142 | //when
143 | //use iter... here
144 |
145 | //then
146 | assertThat(sb.toString()).isEqualToIgnoringCase("123");
147 | }
148 |
149 |
150 | }
151 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J07b_StreamReduceTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import org.junit.Ignore;
4 | import org.junit.Test;
5 |
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | import static org.fest.assertions.api.Assertions.assertThat;
10 |
11 | @Ignore
12 | public class J07b_StreamReduceTest {
13 |
14 | @Test
15 | public void shouldAddNumbersUsingReduce() throws Exception {
16 | //given
17 | final List input = Arrays.asList(2, 3, 5, 7);
18 |
19 | //when
20 | final int sum = input.stream().reduce(0, (acc, x) -> acc + x);
21 |
22 | //then
23 | assertThat(sum).isEqualTo(2 + 3 + 5 + 7);
24 | }
25 |
26 | @Test
27 | public void shouldConcatNumbers() throws Exception {
28 | //given
29 | final List input = Arrays.asList(2, 3, 5, 7);
30 |
31 | //when
32 | final String result = input
33 | .stream()
34 | .reduce(
35 | new StringBuilder(),
36 | (acc, x) -> acc.append(x),
37 | (sb1, sb2) -> sb1.append(sb2))
38 | .toString();
39 |
40 | //then
41 | assertThat(result).isEqualToIgnoringCase("2357");
42 | }
43 |
44 | @Test
45 | public void shouldFindMaxUsingReduce() throws Exception {
46 | //given
47 | final List input = Arrays.asList(4, 2, 6, 3, 8, 1);
48 |
49 | //when
50 | final int max = 0; //input.stream()...
51 |
52 | //then
53 | assertThat(max).isEqualTo(8);
54 | }
55 |
56 | @Test
57 | public void shouldSimulateMapUsingReduce() throws Exception {
58 | //given
59 | final List input = Arrays.asList(2, 3, 5, 7);
60 |
61 | //when
62 | final List doubledPrimes = null; //input.stream()...
63 |
64 | //then
65 | assertThat(doubledPrimes).containsExactly(2 * 2, 3 * 2, 5 * 2, 7 * 2);
66 | }
67 |
68 | @Test
69 | public void shouldSimulateFilterUsingReduce() throws Exception {
70 | //given
71 | final List input = Arrays.asList(2, 3, 4, 5, 6);
72 |
73 | //when
74 | final List onlyEvenNumbers = null; //input.stream()...
75 |
76 | //then
77 | assertThat(onlyEvenNumbers).containsExactly(2, 4, 6);
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J07c_StreamInfiniteTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.util.PrimeUtil;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 |
7 | import java.util.List;
8 | import java.util.stream.LongStream;
9 | import java.util.stream.Stream;
10 |
11 | import static org.fest.assertions.api.Assertions.assertThat;
12 | import static org.fest.assertions.api.Assertions.offset;
13 |
14 | /**
15 | * @see PrimeUtil
16 | */
17 | @Ignore
18 | public class J07c_StreamInfiniteTest {
19 |
20 | @Test
21 | public void shouldGenerateNaturalNumbersAndSumFirstThousand() throws Exception {
22 | //given
23 | final LongStream naturals = LongStream.iterate(1, x -> x + 1);
24 |
25 | //when
26 | final long sum = naturals.limit(1000).sum();
27 |
28 | //then
29 | assertThat(sum).isEqualTo(500500);
30 | }
31 |
32 | @Test
33 | public void shouldCheckForPrimes() throws Exception {
34 | assertThat(PrimeUtil.isPrime(2)).isTrue();
35 | assertThat(PrimeUtil.isPrime(3)).isTrue();
36 | assertThat(PrimeUtil.isPrime(4)).isFalse();
37 | assertThat(PrimeUtil.isPrime(5)).isTrue();
38 | assertThat(PrimeUtil.isPrime(6)).isFalse();
39 | assertThat(PrimeUtil.isPrime(7)).isTrue();
40 | assertThat(PrimeUtil.isPrime(8)).isFalse();
41 | assertThat(PrimeUtil.isPrime(9)).isFalse();
42 | assertThat(PrimeUtil.isPrime(10)).isFalse();
43 | assertThat(PrimeUtil.isPrime(11)).isTrue();
44 | }
45 |
46 | @Test
47 | public void shouldFindNextPrime() throws Exception {
48 | assertThat(PrimeUtil.nextPrimeAfter(2)).isEqualTo(3);
49 | assertThat(PrimeUtil.nextPrimeAfter(3)).isEqualTo(5);
50 | assertThat(PrimeUtil.nextPrimeAfter(4)).isEqualTo(5);
51 | assertThat(PrimeUtil.nextPrimeAfter(5)).isEqualTo(7);
52 | assertThat(PrimeUtil.nextPrimeAfter(6)).isEqualTo(7);
53 | assertThat(PrimeUtil.nextPrimeAfter(7)).isEqualTo(11);
54 | assertThat(PrimeUtil.nextPrimeAfter(8)).isEqualTo(11);
55 | assertThat(PrimeUtil.nextPrimeAfter(9)).isEqualTo(11);
56 | assertThat(PrimeUtil.nextPrimeAfter(10)).isEqualTo(11);
57 | assertThat(PrimeUtil.nextPrimeAfter(11)).isEqualTo(13);
58 | }
59 |
60 | @Test
61 | public void shouldCalculateProductOfFirstFivePrimes() throws Exception {
62 | //given
63 | LongStream primes = LongStream.iterate(2, null);
64 |
65 | //when
66 | final long product = primes.limit(5).reduce(1, (acc, x) -> acc * x);
67 |
68 | //then
69 | assertThat(product).isEqualTo(2 * 3 * 5 * 7 * 11);
70 | }
71 |
72 | @Test
73 | public void shouldGenerateGrowingStrings() throws Exception {
74 | //given
75 | final Stream starStream = Stream.iterate("", null);
76 |
77 | //when
78 | List strings = null;
79 |
80 | //then
81 | assertThat(strings).containsExactly(
82 | "",
83 | "*",
84 | "**",
85 | "***",
86 | "****",
87 | "*****",
88 | "******");
89 | }
90 |
91 | /**
92 | * This method tries to estimate Pi number by randomly generating points on a 2x2 square.
93 | * Then it calculates what's the distance of each point to the center of the square.
94 | * The proportion of points closer than 1 to all of them approximates Pi.
95 | * The more points you take, better approximation you get.
96 | * @see Wikipedia
97 | */
98 | @Test
99 | public void shouldEstimatePi() throws Exception {
100 | //given
101 | Stream randomPoints = null;
102 |
103 | //when
104 | final double piDividedByFour = 0;
105 |
106 | //then
107 | assertThat(piDividedByFour * 4).isEqualTo(Math.PI, offset(0.001));
108 | }
109 |
110 | }
111 |
112 | class Point {
113 | private final double x;
114 | private final double y;
115 |
116 | Point(double x, double y) {
117 | this.x = x;
118 | this.y = y;
119 | }
120 |
121 | public static Point random() {
122 | return new Point(Math.random() * 2 - 1, Math.random() * 2 - 1);
123 | }
124 |
125 | public double distance() {
126 | return Math.sqrt(x * x + y * y);
127 | }
128 |
129 | }
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J07d_CustomCollectorTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.google.common.collect.ImmutableSet;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 |
7 | import java.util.Arrays;
8 | import java.util.Collections;
9 | import java.util.List;
10 | import java.util.Set;
11 | import java.util.stream.LongStream;
12 | import java.util.stream.Stream;
13 |
14 | import static java.util.stream.Collectors.toSet;
15 | import static org.fest.assertions.api.Assertions.assertThat;
16 |
17 | /**
18 | * Implement custom Collector to ImmutableSet from Guava
19 | * @see ImmutableSet#builder()
20 | */
21 | @Ignore
22 | public class J07d_CustomCollectorTest {
23 |
24 | @Test
25 | public void shouldReturnEmptyImmutableSet() throws Exception {
26 | //given
27 | final Set items = Collections.emptySet();
28 |
29 | //when
30 | final ImmutableSet set = null; //items.stream().collect(new ImmutableSetCollector<>());
31 |
32 | //then
33 | assertThat(set).isEmpty();
34 | }
35 |
36 | @Test
37 | public void shouldReturnImmutableSetWithJustOneElement() throws Exception {
38 | //given
39 | final List items = Collections.singletonList(42);
40 |
41 | //when
42 | final ImmutableSet set = null; //items.stream().collect(new ImmutableSetCollector<>());
43 |
44 | //then
45 | assertThat(set).containsExactly(42);
46 | }
47 |
48 | @Test
49 | public void shouldCollectToImmutableSet() throws Exception {
50 | //given
51 | final List items = Arrays.asList(3, 5, 2, 4, 7, 5, 3, 9, 2);
52 |
53 | //when
54 | final ImmutableSet set = null; //items.stream().collect(new ImmutableSetCollector<>());
55 |
56 | //then
57 | assertThat(set).containsOnly(2, 3, 4, 5, 7, 9);
58 | }
59 |
60 | @Test
61 | public void shouldWorkInConcurrentEnvironment() throws Exception {
62 | //given
63 | final Stream longsWithDuplicates = LongStream
64 | .range(0, 100_000)
65 | .parallel()
66 | .mapToObj(x -> x / 2);
67 |
68 | //when
69 | final ImmutableSet set = null; //longsWithDuplicates.collect(new ImmutableSetCollector<>());
70 |
71 | //then
72 | final Set expected = LongStream
73 | .range(0, 100_000 / 2)
74 | .mapToObj(Long::valueOf)
75 | .collect(toSet());
76 | assertThat(set).isEqualTo(expected);
77 | }
78 |
79 | }
80 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J08_FilesTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.people.Person;
4 | import com.nurkiewicz.java8.people.PersonDao;
5 | import org.junit.Ignore;
6 | import org.junit.Test;
7 |
8 | import java.io.IOException;
9 | import java.nio.file.Files;
10 | import java.nio.file.Path;
11 | import java.nio.file.Paths;
12 | import java.util.List;
13 | import java.util.Optional;
14 | import java.util.stream.Stream;
15 |
16 | import static java.util.stream.Collectors.toList;
17 | import static org.fest.assertions.api.Assertions.assertThat;
18 |
19 | /**
20 | * - BufferedReader.lines()
21 | * - Comparator improvements
22 | */
23 | @Ignore
24 | public class J08_FilesTest {
25 |
26 | private final PersonDao dao = new PersonDao();
27 |
28 | @Test
29 | public void shouldLoadAllPeople() throws IOException {
30 | final List people = dao.loadPeopleDatabase();
31 |
32 | assertThat(people).hasSize(137);
33 | }
34 |
35 | @Test
36 | public void shouldSortByName() throws IOException {
37 | final List people = dao.loadPeopleDatabase();
38 |
39 | final List names = people.stream().
40 | map(Person::getName).
41 | distinct().
42 | collect(toList());
43 |
44 | assertThat(names).startsWith("Aleksandar", "Alexander", "Alexandra", "Ali", "Alice");
45 | }
46 |
47 | /**
48 | * Hint: Comparator.comparing()
49 | */
50 | @Test
51 | public void shouldSortFemalesByHeightDesc() throws IOException {
52 | final List people = dao.loadPeopleDatabase();
53 |
54 | final List names = people.stream()
55 | .map(Person::getName)
56 | .collect(toList());
57 |
58 | assertThat(names).startsWith("Mia", "Sevinj", "Anna", "Sofia");
59 | }
60 |
61 | @Test
62 | public void shouldSortByDateOfBirthWhenSameNames() throws IOException {
63 | final List people = dao.loadPeopleDatabase();
64 |
65 | final List names = people.stream().
66 | map(p -> p.getName() + '-' + p.getDateOfBirth().getYear()).
67 | collect(toList());
68 |
69 | assertThat(names).startsWith("Aleksandar-1966", "Alexander-1986", "Alexander-1987", "Alexandra-1988", "Ali-1974");
70 | }
71 |
72 | /**
73 | * @see Files#list(Path)
74 | * @throws Exception
75 | */
76 | @Test
77 | public void shouldGenerateStreamOfAllFilesIncludingSubdirectoriesRecursively() throws Exception {
78 | //given
79 | final String fileToSearch = J08_FilesTest.class.getSimpleName() + ".java";
80 |
81 | //when
82 | final Optional found = filesInDir(Paths.get("."))
83 | .filter(path -> path.endsWith(fileToSearch))
84 | .findAny();
85 |
86 | //then
87 | assertThat(found.isPresent()).isTrue();
88 | }
89 |
90 | private static Stream filesInDir(Path dir) {
91 | throw new UnsupportedOperationException("filesInDir()");
92 | }
93 |
94 | }
95 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J08_LocalDateTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.holidays.Holidays;
4 | import com.nurkiewicz.java8.holidays.PolishHolidays;
5 | import org.junit.Ignore;
6 | import org.junit.Test;
7 |
8 | import java.time.LocalDate;
9 | import java.time.LocalTime;
10 | import java.time.Period;
11 | import java.time.ZoneId;
12 | import java.time.ZonedDateTime;
13 | import java.time.temporal.TemporalAdjuster;
14 | import java.time.temporal.TemporalAdjusters;
15 | import java.util.stream.Stream;
16 |
17 | import static java.time.Month.DECEMBER;
18 | import static java.time.Month.MAY;
19 | import static java.time.Month.SEPTEMBER;
20 | import static org.fest.assertions.api.Assertions.assertThat;
21 |
22 | @Ignore
23 | public class J08_LocalDateTest {
24 |
25 | private final Holidays holidays = new PolishHolidays();
26 |
27 | /**
28 | * Hint: consider iterate(), limit() and filter()
29 | * @throws Exception
30 | */
31 | @Test
32 | public void shouldCountNumberOfHolidaysIn2014() throws Exception {
33 | //given
34 | final Stream holidaysIn2014 = null;
35 |
36 | //when
37 | final long numberOfHolidays = holidaysIn2014.count();
38 |
39 | //then
40 | assertThat(numberOfHolidays).isEqualTo(113);
41 | }
42 |
43 | /**
44 | * @see TemporalAdjusters
45 | */
46 | @Test
47 | public void shouldApplyBuiltIntTemporalAdjuster() throws Exception {
48 | //given
49 | final LocalDate today = LocalDate.of(2014, MAY, 12);
50 |
51 | //when
52 | final LocalDate previousWednesday = today;
53 |
54 | //then
55 | assertThat(previousWednesday).isEqualTo(LocalDate.of(2014, MAY, 7));
56 | }
57 |
58 | @Test
59 | public void shouldApplyCustomTemporalAdjuster() throws Exception {
60 | //given
61 | final LocalDate today = LocalDate.of(2014, MAY, 12);
62 |
63 | //when
64 | final LocalDate nextHoliday = today.with(nextHoliday());
65 |
66 | //then
67 | assertThat(nextHoliday).isEqualTo(LocalDate.of(2014, MAY, 17));
68 | }
69 |
70 | public TemporalAdjuster nextHoliday() {
71 | throw new UnsupportedOperationException("nextHoliday()");
72 | }
73 |
74 | /**
75 | * - Calculate time after billion seconds from given date
76 | * - What will be the hour in Asia/Tokyo"
77 | * - See how period can be calculated
78 | * @throws Exception
79 | */
80 | @Test
81 | public void shouldFindWhenIhaveBillionthSecondBirthday() throws Exception {
82 | //given
83 | final LocalDate dateOfBirth = LocalDate.of(1985, DECEMBER, 25);
84 | final LocalTime timeOfBirth = LocalTime.of(22, 10);
85 | final ZonedDateTime birth = ZonedDateTime.of(dateOfBirth, timeOfBirth, ZoneId.of("Europe/Warsaw"));
86 |
87 | //when
88 | final ZonedDateTime billionSecondsLater = birth;
89 | final int hourInTokyo = billionSecondsLater.getHour();
90 |
91 | //then
92 | final Period periodToBillionth = Period.between(
93 | LocalDate.of(2014, MAY, 12),
94 | billionSecondsLater.toLocalDate());
95 | assertThat(billionSecondsLater.toLocalDate()).isEqualTo(LocalDate.of(2017, SEPTEMBER, 3));
96 | assertThat(hourInTokyo).isEqualTo(7);
97 | assertThat(periodToBillionth.getYears()).isEqualTo(3);
98 | assertThat(periodToBillionth.getMonths()).isEqualTo(3);
99 | }
100 |
101 | }
102 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J08_NewMapMethodsTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.util.LoremIpsum;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 |
7 | import java.util.Map;
8 | import java.util.Set;
9 |
10 | import static org.fest.assertions.api.Assertions.assertThat;
11 | import static org.fest.assertions.api.Assertions.entry;
12 |
13 | @Ignore
14 | public class J08_NewMapMethodsTest {
15 |
16 | @Test
17 | public void shouldReturnWordCount() throws Exception {
18 | //given
19 | final String loremIpsum = LoremIpsum.text();
20 |
21 | //when
22 | Map wordCount = LoremIpsum.wordCount(loremIpsum);
23 |
24 | //then
25 | assertThat(wordCount)
26 | .hasSize(140)
27 | .contains(
28 | entry("eget", 12),
29 | entry("sit", 9),
30 | entry("amet", 9),
31 | entry("et", 8)
32 | );
33 |
34 | assertThat(wordCount.getOrDefault("kot", 0)).isZero();
35 | }
36 |
37 | @Test
38 | public void shouldReturnTotalWords() throws Exception {
39 | //given
40 | final String loremIpsum = LoremIpsum.text();
41 | Map wordCount = LoremIpsum.wordCount(loremIpsum);
42 |
43 | //when
44 | int totalWords = 0; //wordCount...
45 |
46 | //then
47 | assertThat(totalWords).isEqualTo(441);
48 | }
49 |
50 | @Test
51 | public void shouldReturnFiveMostCommonWords() throws Exception {
52 | final String loremIpsum = LoremIpsum.text();
53 | Map wordCount = LoremIpsum.wordCount(loremIpsum);
54 |
55 | //when
56 | final Set fiveMostCommon = null; //wordCount...
57 |
58 | //then
59 | assertThat(fiveMostCommon).containsOnly("eget", "sit", "amet", "et", "sed");
60 | }
61 |
62 | @Test
63 | public void shouldReturnWordsThatOccurOnlyOnce() throws Exception {
64 | final String loremIpsum = LoremIpsum.text();
65 | Map wordCount = LoremIpsum.wordCount(loremIpsum);
66 |
67 | //when
68 | final Set uniqueWords = null; //wordCount...
69 |
70 | //then
71 | assertThat(uniqueWords)
72 | .hasSize(37)
73 | .contains("tempor", "laoreet", "netus");
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J09_CollectorsTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.people.Person;
4 | import com.nurkiewicz.java8.people.PersonDao;
5 | import org.junit.Ignore;
6 | import org.junit.Test;
7 |
8 | import java.io.IOException;
9 | import java.util.Collections;
10 | import java.util.IntSummaryStatistics;
11 | import java.util.List;
12 | import java.util.Map;
13 |
14 | import static org.fest.assertions.api.Assertions.assertThat;
15 | import static org.fest.assertions.data.Offset.offset;
16 |
17 | /**
18 | * Explore different Collectors.* implementations
19 | * - Various collectors, grouping, average, toList, etc.
20 | */
21 | @Ignore
22 | public class J09_CollectorsTest {
23 |
24 | private final PersonDao dao = new PersonDao();
25 |
26 | @Test
27 | public void calculateAverageHeight() throws IOException {
28 | final List people = dao.loadPeopleDatabase();
29 |
30 | final Double averageHeight = 0.0; // people.stream().
31 |
32 | assertThat(averageHeight).isEqualTo(174, offset(0.5));
33 | }
34 |
35 | @Test
36 | public void partitionByPeopleAboveAndBelow180CmHeight() throws IOException {
37 | final List people = dao.loadPeopleDatabase();
38 |
39 | final Map> peopleByHeight = Collections.emptyMap(); // people.stream().
40 |
41 | final List tallPeople = peopleByHeight.get(true);
42 | assertThat(tallPeople).hasSize(33);
43 |
44 | final List shortPeople = peopleByHeight.get(false);
45 | assertThat(shortPeople).hasSize(104);
46 | }
47 |
48 | @Test
49 | public void groupPeopleByWeight() throws IOException {
50 | final List people = dao.loadPeopleDatabase();
51 |
52 | final Map> peopleByWeight = Collections.emptyMap(); // people.stream().
53 |
54 | assertThat(peopleByWeight.get(46)).hasSize(1);
55 | assertThat(peopleByWeight.get(70)).hasSize(2);
56 | assertThat(peopleByWeight.get(92)).hasSize(1);
57 | }
58 |
59 | @Test
60 | public void weightStatistics() throws IOException {
61 | final List people = dao.loadPeopleDatabase();
62 |
63 | final IntSummaryStatistics stats = new IntSummaryStatistics(); // people.stream().
64 |
65 | assertThat(stats.getCount()).isEqualTo(137);
66 | assertThat(stats.getMin()).isEqualTo(46);
67 | assertThat(stats.getMax()).isEqualTo(92);
68 | assertThat(stats.getSum()).isEqualTo(8998);
69 | assertThat(stats.getAverage()).isEqualTo(65.8, offset(0.5));
70 | }
71 |
72 | }
73 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J09_StringsTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import org.junit.Ignore;
4 | import org.junit.Test;
5 |
6 | import java.util.Arrays;
7 | import java.util.List;
8 |
9 | import static org.fest.assertions.api.Assertions.assertThat;
10 |
11 | /**
12 | * Hint: String.chars()
13 | */
14 | @Ignore
15 | public class J09_StringsTest {
16 |
17 | @Test
18 | public void arrAllCharactersDigits() throws Exception {
19 | assertThat(onlyDigits("+12 345-678 (90)")).isFalse();
20 | assertThat(onlyDigits("100 200 300")).isFalse();
21 | assertThat(onlyDigits("1234567890")).isTrue();
22 | }
23 |
24 | private boolean onlyDigits(String phone) {
25 | return true;
26 | }
27 |
28 | @Test
29 | public void hasAnyNonAlphabeticCharacters() throws Exception {
30 | assertThat(anyNonAlphabetic("abc")).isFalse();
31 | assertThat(anyNonAlphabetic("CamelCase")).isFalse();
32 | assertThat(anyNonAlphabetic("_underscore")).isTrue();
33 | assertThat(anyNonAlphabetic("Big bang!")).isTrue();
34 | assertThat(anyNonAlphabetic("#%@")).isTrue();
35 | }
36 |
37 | private boolean anyNonAlphabetic(String s) {
38 | return true;
39 | }
40 |
41 | /**
42 | * Hint: String.join()
43 | */
44 | @Test
45 | public void shouldJoinMultipleStringsIntoString() throws Exception {
46 | //given
47 | final List ids = Arrays.asList("1", "2", "3", "4");
48 |
49 | //when
50 | final String joined = "";
51 |
52 | //then
53 | assertThat(joined).isEqualTo("1, 2, 3, 4");
54 | }
55 |
56 | @Test
57 | public void shouldJoinMultipleIntsIntoString() throws Exception {
58 | //given
59 | final List ids = Arrays.asList(1, 2, 3, 4);
60 |
61 | //when
62 | final String joined = "";
63 |
64 | //then
65 | assertThat(joined).isEqualTo("1, 2, 3, 4");
66 | }
67 |
68 | /**
69 | * Hint: StringJoiner
70 | */
71 | @Test
72 | public void shouldJoinSeparateStrings() throws Exception {
73 | //given
74 | String x = "X";
75 | String y = "Y";
76 | String z = "Z";
77 |
78 | //when
79 | String joined = "";
80 |
81 | //then
82 | assertThat(joined).isEqualTo("");
83 | }
84 |
85 | }
86 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J10_ParallelStreamsTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.people.Person;
4 | import com.nurkiewicz.java8.people.PersonDao;
5 | import org.junit.Ignore;
6 | import org.junit.Test;
7 |
8 | import java.io.IOException;
9 | import java.util.List;
10 |
11 | import static java.util.stream.Collectors.toList;
12 | import static org.fest.assertions.api.Assertions.assertThat;
13 |
14 | /**
15 | * - run time difference
16 | * - unspecified order
17 | * - commonPool()
18 | */
19 | @Ignore
20 | public class J10_ParallelStreamsTest {
21 |
22 | private final PersonDao dao = new PersonDao();
23 |
24 | @Test
25 | public void parallel() throws IOException {
26 | final List veryTallParallel = dao.loadPeopleDatabase()
27 | .parallelStream()
28 | .filter(p -> p.getHeight() > 190)
29 | .collect(toList());
30 | final List veryTall = dao.loadPeopleDatabase()
31 | .stream()
32 | .filter(p -> p.getHeight() > 190)
33 | .collect(toList());
34 |
35 | assertThat(veryTallParallel).isEqualTo(veryTall);
36 | }
37 |
38 |
39 | }
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J11_AtomicTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.atomic.EventCounter;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 |
7 | import static com.jayway.awaitility.Awaitility.await;
8 | import static com.jayway.awaitility.Awaitility.to;
9 | import static org.fest.assertions.api.Assertions.assertThat;
10 | import static org.hamcrest.CoreMatchers.is;
11 |
12 | /**
13 | * *Adder
14 | * *Accumulator
15 | * Atomic* improvements
16 | * - Decide which atomic.* class best suits given requirements
17 | * @see Java Concurrent Counters By Numbers
18 | */
19 | @Ignore
20 | public class J11_AtomicTest {
21 |
22 | @Test
23 | public void shouldCountMultipleEvents() throws Exception {
24 | //given
25 | final EventCounter counter = new EventCounter();
26 |
27 | //when
28 | counter.incBy(1);
29 | counter.incBy(3);
30 | counter.incBy(2);
31 |
32 | //then
33 | assertThat(counter.longValue()).isEqualTo(1 + 3 + 2);
34 | }
35 |
36 | @Test
37 | public void shouldResetAndRememberOldValue() throws Exception {
38 | //given
39 | final EventCounter counter = new EventCounter();
40 |
41 | //when
42 | counter.incBy(1);
43 | counter.incBy(2);
44 | final long last = counter.reset();
45 |
46 | //then
47 | assertThat(counter.longValue()).isZero();
48 | assertThat(last).isEqualTo(1 + 2);
49 | }
50 |
51 | @Test
52 | public void shouldCountEventsInMultipleThreads() throws Exception {
53 | //given
54 | final EventCounter counter = new EventCounter();
55 |
56 | //when
57 | MultiRunner.runMultiThreaded(1000, () -> counter.incBy(1));
58 |
59 | //then
60 | await().untilCall(to(counter).longValue(), is(1000L));
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J11b_AtomicTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.atomic.RangeCollector;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 |
7 | import static com.jayway.awaitility.Awaitility.await;
8 | import static com.jayway.awaitility.Awaitility.to;
9 | import static org.fest.assertions.api.Assertions.assertThat;
10 | import static org.fest.assertions.api.Assertions.offset;
11 | import static org.hamcrest.Matchers.closeTo;
12 |
13 | /**
14 | * *Adder
15 | * *Accumulator
16 | * Atomic* improvements
17 | * - Decide which atomic.* class best suits given requirements
18 | */
19 | @Ignore
20 | public class J11b_AtomicTest {
21 |
22 | @Test
23 | public void shouldHaveExtremeRangesInTheBeginning() throws Exception {
24 | //given
25 | final RangeCollector range = new RangeCollector();
26 |
27 | //when
28 | final double min = range.getMin();
29 | final double max = range.getMax();
30 |
31 | //then
32 | assertThat(min).isEqualTo(Double.MAX_VALUE);
33 | assertThat(max).isEqualTo(Double.MIN_VALUE);
34 | }
35 |
36 | @Test
37 | public void shouldCountSingleValueAsBothMinAndMax() throws Exception {
38 | //given
39 | final RangeCollector range = new RangeCollector();
40 | final int someValue = 42;
41 |
42 | //when
43 | range.save(someValue);
44 |
45 | //then
46 | assertThat(range.getMin()).isEqualTo(someValue, offset(0.1));
47 | assertThat(range.getMax()).isEqualTo(someValue, offset(0.1));
48 | }
49 |
50 | @Test
51 | public void shouldRememberMinAndMaxOfMultipleValues() throws Exception {
52 | //given
53 | final RangeCollector range = new RangeCollector();
54 |
55 | //when
56 | range.save(3);
57 | range.save(1);
58 | range.save(5);
59 | range.save(-1);
60 | range.save(2);
61 |
62 | //then
63 | assertThat(range.getMin()).isEqualTo(-1, offset(0.1));
64 | assertThat(range.getMax()).isEqualTo(5, offset(0.1));
65 | }
66 |
67 | @Test
68 | public void shouldRememberMinAndMaxInMultipleThreads() throws Exception {
69 | //given
70 | final RangeCollector range = new RangeCollector();
71 |
72 | //when
73 | MultiRunner.runMultiThreaded(1000, () -> range.save(randomDigit()));
74 |
75 | //then
76 | await().untilCall(to(range).getMin(), closeTo(0, 0.01));
77 | await().untilCall(to(range).getMax(), closeTo(9, 0.01));
78 | }
79 |
80 | private int randomDigit() {
81 | return (int) (Math.random() * 10);
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J11c_AtomicTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.atomic.SafeCalculator;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 |
7 | import java.util.stream.IntStream;
8 |
9 | import static com.jayway.awaitility.Awaitility.await;
10 | import static com.jayway.awaitility.Awaitility.to;
11 | import static org.fest.assertions.api.Assertions.assertThat;
12 | import static org.fest.assertions.api.Assertions.offset;
13 | import static org.hamcrest.Matchers.closeTo;
14 |
15 | /**
16 | * *Adder
17 | * *Accumulator
18 | * Atomic* improvements
19 | * - Decide which atomic.* class best suits given requirements
20 | */
21 | @Ignore
22 | public class J11c_AtomicTest {
23 |
24 | @Test
25 | public void shouldReturnZeroWhenNoPreviousInteractionsWithTheCalulator() throws Exception {
26 | //given
27 | final SafeCalculator calculator = new SafeCalculator();
28 |
29 | //when
30 | final double result = calculator.doubleValue();
31 |
32 | //then
33 | assertThat(result).isEqualTo(0.0, offset(0.1));
34 | }
35 |
36 | @Test
37 | public void shouldCorrectlyApplyAllOperations() throws Exception {
38 | //given
39 | final SafeCalculator calculator = new SafeCalculator();
40 |
41 | //when
42 | final int i1 = calculator.add(3); //0 -> 3
43 | final int i2 = calculator.sub(1); //3 -> 2
44 | final int i3 = calculator.mul(4); //2 -> 8
45 | final int i4 = calculator.div(2); //8 -> 4
46 |
47 | //then
48 | assertThat(i1).isZero();
49 | assertThat(i2).isEqualTo(3);
50 | assertThat(i3).isEqualTo(2);
51 | assertThat(i4).isEqualTo(8);
52 | assertThat(calculator.intValue()).isEqualTo(4);
53 | }
54 |
55 | @Test
56 | public void shouldResetToGivenValueAndReturnPrevious() throws Exception {
57 | //given
58 | final SafeCalculator calculator = new SafeCalculator();
59 |
60 | //when
61 | calculator.add(4); //4
62 | calculator.sub(-1); //5
63 | final double tmp = calculator.set(3); //3
64 | calculator.mul(2); //6
65 | calculator.div(3); //2
66 |
67 | //then
68 | assertThat(tmp).isEqualTo(5.0, offset(0.1));
69 | assertThat(calculator.doubleValue()).isEqualTo(2.0, offset(0.1));
70 | }
71 |
72 | @Test
73 | public void shouldCalculateInMultipleThreads() throws Exception {
74 | //given
75 | final SafeCalculator calculator = new SafeCalculator();
76 |
77 | //when
78 | IntStream.range(1, 5000).forEach(i ->
79 | MultiRunner.runMultiThreaded(() -> calculator.add(i)));
80 |
81 | //then
82 | final int expectedSum = IntStream.range(1, 5000).sum();
83 | await().untilCall(to(calculator).doubleValue(), closeTo(expectedSum, 0.01));
84 | }
85 |
86 | }
87 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J12_BigDecimalAccumulatorTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.atomic.BigDecimalAccumulator;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 |
7 | import java.math.BigDecimal;
8 |
9 | import static com.jayway.awaitility.Awaitility.await;
10 | import static org.fest.assertions.api.Assertions.assertThat;
11 |
12 | /**
13 | * Implement {@link BigDecimalAccumulator} so that it satisfies tests below.
14 | */
15 | @Ignore
16 | public class J12_BigDecimalAccumulatorTest {
17 |
18 | @Test
19 | public void shouldFirstReturnInitialValue() {
20 | //given
21 | final BigDecimalAccumulator accumulator = new BigDecimalAccumulator(BigDecimal.ZERO, (a, x) -> a.add(x));
22 |
23 | //when
24 | final BigDecimal initial = accumulator.get();
25 |
26 | //then
27 | assertThat(initial).isEqualByComparingTo(BigDecimal.ZERO);
28 | }
29 |
30 | @Test
31 | public void shouldResetToInitialValue() throws Exception {
32 | //given
33 | final BigDecimalAccumulator accumulator = new BigDecimalAccumulator(BigDecimal.ONE, (a, x) -> a.multiply(x));
34 |
35 | //when
36 | accumulator.reset();
37 |
38 | //then
39 | assertThat(accumulator.get()).isEqualByComparingTo(BigDecimal.ONE);
40 | }
41 |
42 | @Test
43 | public void shouldReturnAndResetToInitialValue() throws Exception {
44 | //given
45 | final BigDecimalAccumulator accumulator = new BigDecimalAccumulator(BigDecimal.ONE, (a, x) -> a.multiply(x));
46 |
47 | //when
48 | final BigDecimal initial = accumulator.getAndReset();
49 |
50 | //then
51 | assertThat(initial).isEqualByComparingTo(BigDecimal.ONE);
52 | }
53 |
54 | @Test
55 | public void shouldAccumulateOneValue() throws Exception {
56 | //given
57 | final BigDecimalAccumulator accumulator = new BigDecimalAccumulator(BigDecimal.ZERO, (a, x) -> a.add(x));
58 |
59 | //when
60 | accumulator.accumulate(BigDecimal.TEN);
61 |
62 | //then
63 | assertThat(accumulator.get()).isEqualByComparingTo(BigDecimal.TEN);
64 | }
65 |
66 | @Test
67 | public void shouldAccumulateMultipleValues() throws Exception {
68 | //given
69 | final BigDecimalAccumulator accumulator = new BigDecimalAccumulator(BigDecimal.ZERO, (a, x) -> a.add(x));
70 |
71 | //when
72 | accumulator.accumulate(BigDecimal.valueOf(1));
73 | accumulator.accumulate(BigDecimal.valueOf(3));
74 | accumulator.accumulate(BigDecimal.valueOf(2));
75 |
76 | //then
77 | assertThat(accumulator.get()).isEqualByComparingTo(BigDecimal.valueOf(1 + 3 + 2));
78 | }
79 |
80 | @Test
81 | public void shouldAccumulateMaximum() throws Exception {
82 | //given
83 | final BigDecimalAccumulator accumulator = new BigDecimalAccumulator(BigDecimal.ZERO, (a, x) -> a.max(x));
84 |
85 | //when
86 | accumulator.accumulate(BigDecimal.valueOf(1));
87 | accumulator.accumulate(BigDecimal.valueOf(7));
88 | accumulator.accumulate(BigDecimal.valueOf(2));
89 | accumulator.accumulate(BigDecimal.valueOf(3));
90 |
91 | //then
92 | assertThat(accumulator.get()).isEqualByComparingTo(BigDecimal.valueOf(7));
93 | }
94 |
95 | @Test
96 | public void shouldCorrectlyAccumulateFromMultipleThreads() throws Exception {
97 | //given
98 | final BigDecimalAccumulator accumulator = new BigDecimalAccumulator(BigDecimal.ZERO, (a, x) -> a.add(x));
99 | final int count = 1000;
100 |
101 | //when
102 | MultiRunner.runMultiThreaded(count, () -> accumulator.accumulate(BigDecimal.ONE));
103 |
104 | //then
105 | await().until(() -> accumulator.get().intValue() == count);
106 | }
107 |
108 | }
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J13_AsyncAgentTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.agent.Agent;
4 | import org.junit.After;
5 | import org.junit.Ignore;
6 | import org.junit.Test;
7 |
8 | import java.math.BigInteger;
9 | import java.util.HashSet;
10 | import java.util.List;
11 | import java.util.Set;
12 | import java.util.concurrent.ExecutorService;
13 | import java.util.concurrent.Executors;
14 | import java.util.concurrent.TimeUnit;
15 | import java.util.stream.IntStream;
16 |
17 | import static com.jayway.awaitility.Awaitility.await;
18 | import static com.jayway.awaitility.Awaitility.to;
19 | import static java.util.stream.Collectors.toList;
20 | import static org.fest.assertions.api.Assertions.assertThat;
21 | import static org.hamcrest.CoreMatchers.is;
22 | import static org.hamcrest.Matchers.hasSize;
23 | import static org.hamcrest.Matchers.not;
24 |
25 | @Ignore
26 | public class J13_AsyncAgentTest {
27 |
28 | private ExecutorService pool = Executors.newFixedThreadPool(100);
29 |
30 | @After
31 | public void stopPool() {
32 | pool.shutdown();
33 | }
34 |
35 | public void newAgentShouldHaveInitialValue() {
36 | //given
37 | final Agent agent = Agent.create(42);
38 |
39 | //when
40 | final int actual = agent.get();
41 |
42 | //then
43 | assertThat(actual).isEqualTo(42);
44 | }
45 |
46 | @Test
47 | public void shouldApplyTwoChanges() {
48 | //given
49 | final Agent agent = Agent.create(BigInteger.ONE);
50 |
51 | //when
52 | agent.send(x -> x.add(BigInteger.ONE));
53 | agent.send(x -> x.add(BigInteger.TEN));
54 |
55 | //then
56 | await().until(() -> agent.get().equals(BigInteger.valueOf(1 + 1 + 10)));
57 | }
58 |
59 | @Test
60 | public void shouldApplyChangesFromOneThreadInOrder() {
61 | //given
62 | final Agent agent = Agent.create("");
63 |
64 | //when
65 | agent.send(s -> s + "A");
66 | agent.send(s -> s + "B");
67 | agent.send(s -> s + "C");
68 | agent.send(String::toLowerCase);
69 | agent.send(s -> "D" + s);
70 |
71 | //then
72 | await().untilCall(to(agent).get(), is("Dabc"));
73 | }
74 |
75 | @Test
76 | public void shouldRunInDifferentThread() {
77 | //given
78 | final long mainThreadId = Thread.currentThread().getId();
79 | final Agent agent = Agent.create(mainThreadId);
80 |
81 | //when
82 | agent.send(x -> Thread.currentThread().getId());
83 |
84 | //then
85 | await().untilCall(to(agent).get(), is(not(mainThreadId)));
86 | }
87 |
88 | @Test
89 | public void aLotOfAgents() throws InterruptedException {
90 | //given
91 | final int totalAgents = 50_000;
92 | final List> agents = IntStream
93 | .range(0, totalAgents)
94 | .boxed()
95 | .map(i -> Agent.create(""))
96 | .collect(toList());
97 |
98 | //when
99 | agents.forEach(a -> {
100 | a.send(s -> s + "a");
101 | a.send(s -> s + "b");
102 | a.send(s -> s + "c");
103 | a.send(s -> s + "d");
104 | a.send(s -> s + "e");
105 | a.send(s -> s + "f");
106 | });
107 |
108 | //then
109 | agents.forEach(this::waitForCorrectResult);
110 | }
111 |
112 | private void waitForCorrectResult(Agent a) {
113 | await()
114 | .pollInterval(1, TimeUnit.MILLISECONDS)
115 | .pollDelay(1, TimeUnit.NANOSECONDS)
116 | .until(a::get, is("abcdef"));
117 | }
118 |
119 | @Test
120 | public void shouldMutateObjectInsideAgent() throws Exception {
121 | //given
122 | final Agent> agent = Agent.create(new HashSet<>());
123 | final int total = 10_000;
124 |
125 | //when
126 | IntStream
127 | .range(0, total)
128 | .forEach(i ->
129 | agent.send(set -> {
130 | set.add(i);
131 | return set;
132 | }));
133 |
134 | //then
135 | await().untilCall(to(agent).get(), hasSize(total));
136 | }
137 |
138 | }
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J21_FuturesIntroductionTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.stackoverflow.LoadFromStackOverflowTask;
4 | import com.nurkiewicz.java8.util.AbstractFuturesTest;
5 | import org.junit.Ignore;
6 | import org.junit.Test;
7 | import org.slf4j.Logger;
8 | import org.slf4j.LoggerFactory;
9 |
10 | import java.util.concurrent.Callable;
11 | import java.util.concurrent.Future;
12 |
13 | @Ignore
14 | public class J21_FuturesIntroductionTest extends AbstractFuturesTest {
15 |
16 | private static final Logger log = LoggerFactory.getLogger(J21_FuturesIntroductionTest.class);
17 |
18 | @Test
19 | public void blockingCall() throws Exception {
20 | final String title = client.mostRecentQuestionAbout("java");
21 | log.debug("Most recent Java question: '{}'", title);
22 | }
23 |
24 | @Test
25 | public void executorService() throws Exception {
26 | final Callable task = () -> client.mostRecentQuestionAbout("java");
27 | final Future javaQuestionFuture = executorService.submit(task);
28 | final String javaQuestion = javaQuestionFuture.get();
29 | log.debug("Found: '{}'", javaQuestion);
30 | }
31 |
32 | @Test
33 | public void waitForFirstOrAll() throws Exception {
34 | final Future java = findQuestionsAbout("java");
35 | final Future scala = findQuestionsAbout("scala");
36 |
37 | //???
38 | }
39 |
40 | @Test
41 | public void runWhenFirstFinished() throws Exception {
42 | final Future java = findQuestionsAbout("java");
43 | final Future scala = findQuestionsAbout("scala");
44 | //???
45 | }
46 |
47 | private Future findQuestionsAbout(String tag) {
48 | final Callable task = new LoadFromStackOverflowTask(client, tag);
49 | return executorService.submit(task);
50 | }
51 |
52 | }
53 |
54 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J22_CreatingTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.util.AbstractFuturesTest;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.util.concurrent.CompletableFuture;
10 |
11 | @Ignore
12 | public class J22_CreatingTest extends AbstractFuturesTest {
13 |
14 | private static final Logger log = LoggerFactory.getLogger(J22_CreatingTest.class);
15 |
16 | @Test
17 | public void supplyAsync() throws Exception {
18 | final CompletableFuture java = CompletableFuture.supplyAsync(() ->
19 | client.mostRecentQuestionAbout("java")
20 | );
21 | log.debug("Found: '{}'", java.get());
22 | }
23 |
24 | @Test
25 | public void supplyAsyncWithCustomExecutor() throws Exception {
26 | final CompletableFuture java = CompletableFuture.supplyAsync(() ->
27 | client.mostRecentQuestionAbout("java"),
28 | executorService);
29 | log.debug("Found: '{}'", java.get());
30 | }
31 |
32 | }
33 |
34 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J23_MapTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.util.AbstractFuturesTest;
4 | import org.jsoup.nodes.Document;
5 | import org.jsoup.nodes.Element;
6 | import org.junit.Ignore;
7 | import org.junit.Test;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 |
11 | import java.util.concurrent.CompletableFuture;
12 |
13 | @Ignore
14 | public class J23_MapTest extends AbstractFuturesTest {
15 |
16 | private static final Logger log = LoggerFactory.getLogger(J23_MapTest.class);
17 |
18 | @Test
19 | public void oldSchool() throws Exception {
20 | final CompletableFuture java = CompletableFuture.supplyAsync(() ->
21 | client.mostRecentQuestionsAbout("java"),
22 | executorService);
23 |
24 | final Document document = java.get(); //blocks
25 | final Element element = document.select("a.question-hyperlink").get(0);
26 | final String title = element.text();
27 | final int length = title.length();
28 | log.debug("Length: {}", length);
29 | }
30 |
31 | @Test
32 | public void thenApply() throws Exception {
33 | final CompletableFuture java = CompletableFuture.supplyAsync(() ->
34 | client.mostRecentQuestionsAbout("java"),
35 | executorService);
36 |
37 | final CompletableFuture titleElement =
38 | java.thenApply((Document doc) -> doc.select("a.question-hyperlink").get(0));
39 |
40 | final CompletableFuture titleText =
41 | titleElement.thenApply(Element::text);
42 |
43 | final CompletableFuture length =
44 | titleText.thenApply(String::length);
45 |
46 | log.debug("Length: {}", length.get());
47 | }
48 |
49 | @Test
50 | public void thenApplyChained() throws Exception {
51 | final CompletableFuture java = CompletableFuture.supplyAsync(() ->
52 | client.mostRecentQuestionsAbout("java"),
53 | executorService);
54 |
55 | final CompletableFuture length = java.
56 | thenApply(doc -> doc.select("a.question-hyperlink").get(0)).
57 | thenApply(Element::text).
58 | thenApply(String::length);
59 |
60 | log.debug("Length: {}", length.get());
61 | }
62 |
63 | @Test
64 | public void thenApplySingleStep() throws Exception {
65 | final CompletableFuture java = CompletableFuture.supplyAsync(() ->
66 | client.mostRecentQuestionsAbout("java"),
67 | executorService);
68 |
69 | final CompletableFuture length = java.
70 | thenApply(doc ->
71 | doc.select("a.question-hyperlink").
72 | get(0).
73 | text().
74 | length());
75 |
76 | log.debug("Length: {}", length.get());
77 | }
78 |
79 | }
80 |
81 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J24_FlatMapTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.stackoverflow.Question;
4 | import com.nurkiewicz.java8.util.AbstractFuturesTest;
5 | import org.jsoup.nodes.Document;
6 | import org.junit.Ignore;
7 | import org.junit.Test;
8 | import org.slf4j.Logger;
9 | import org.slf4j.LoggerFactory;
10 | import org.springframework.http.HttpStatus;
11 |
12 | import java.util.concurrent.CompletableFuture;
13 | import java.util.concurrent.ExecutorService;
14 | import java.util.concurrent.Executors;
15 |
16 | @Ignore
17 | public class J24_FlatMapTest extends AbstractFuturesTest {
18 |
19 | private static final Logger log = LoggerFactory.getLogger(J24_FlatMapTest.class);
20 |
21 | private CompletableFuture javaQuestions() {
22 | return CompletableFuture.supplyAsync(() ->
23 | client.mostRecentQuestionsAbout("java"),
24 | executorService);
25 | }
26 |
27 | private CompletableFuture findMostInterestingQuestion(Document document) {
28 | return CompletableFuture.completedFuture(new Question());
29 | }
30 |
31 | private CompletableFuture googleAnswer(Question q) {
32 | return CompletableFuture.completedFuture("42");
33 | }
34 |
35 | private CompletableFuture postAnswer(String answer) {
36 | return CompletableFuture.completedFuture(200);
37 | }
38 |
39 | @Test
40 | public void thenApplyIsWrong() throws Exception {
41 | final CompletableFuture> future =
42 | javaQuestions().thenApply(this::findMostInterestingQuestion);
43 | }
44 |
45 | @Test
46 | public void thenAcceptIsPoor() throws Exception {
47 | javaQuestions().thenAccept(document -> {
48 | findMostInterestingQuestion(document).thenAccept(question -> {
49 | googleAnswer(question).thenAccept(answer -> {
50 | postAnswer(answer).thenAccept(status -> {
51 | if (status == HttpStatus.OK.value()) {
52 | log.debug("OK");
53 | } else {
54 | log.error("Wrong status code: {}", status);
55 | }
56 | });
57 | });
58 | });
59 | });
60 | }
61 |
62 | @Test
63 | public void thenCompose() throws Exception {
64 | final CompletableFuture java = javaQuestions();
65 |
66 | final CompletableFuture questionFuture =
67 | java.thenCompose(this::findMostInterestingQuestion);
68 |
69 | final CompletableFuture answerFuture =
70 | questionFuture.thenCompose(this::googleAnswer);
71 |
72 | final CompletableFuture httpStatusFuture =
73 | answerFuture.thenCompose(this::postAnswer);
74 |
75 | httpStatusFuture.thenAccept(status -> {
76 | if (status == HttpStatus.OK.value()) {
77 | log.debug("OK");
78 | } else {
79 | log.error("Wrong status code: {}", status);
80 | }
81 | });
82 | }
83 |
84 | @Test
85 | public void chained() throws Exception {
86 |
87 | ExecutorService pool =
88 | Executors.newFixedThreadPool(10);
89 |
90 | CompletableFuture future =
91 | CompletableFuture.supplyAsync(() ->
92 | loadWebPage("www.wikipedia.org"),
93 | pool);
94 |
95 | future.
96 | thenApply(this::parse).
97 | thenCompose(this::keywords).
98 | thenAccept(System.out::println);
99 |
100 | }
101 |
102 | private String loadWebPage(String s) {
103 | return null;
104 | }
105 |
106 | Document parse(String html) {
107 | return null;
108 | }
109 |
110 | CompletableFuture keywords(Document doc) {
111 | //...
112 | return null;
113 | }
114 |
115 | }
116 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J25_ZipTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.util.AbstractFuturesTest;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.util.concurrent.CompletableFuture;
10 |
11 | @Ignore
12 | public class J25_ZipTest extends AbstractFuturesTest {
13 |
14 | private static final Logger log = LoggerFactory.getLogger(J25_ZipTest.class);
15 |
16 | @Test
17 | public void thenCombine() throws Exception {
18 | final CompletableFuture java = questions("java");
19 | final CompletableFuture scala = questions("scala");
20 |
21 | final CompletableFuture both = java.
22 | thenCombine(scala, (String javaTitle, String scalaTitle) ->
23 | javaTitle.length() + scalaTitle.length()
24 | );
25 |
26 | both.thenAccept(length -> log.debug("Total length: {}", length));
27 |
28 |
29 | final CompletableFuture f1 = null; //...
30 | final CompletableFuture f2 = null; //...
31 |
32 | final CompletableFuture sum = f1.thenCombine(f2, (i1, i2) -> (i1 + i2 / 2.0));
33 |
34 | f1.acceptEither(f2, System.out::println);
35 | }
36 |
37 | @Test
38 | public void either() throws Exception {
39 | final CompletableFuture java = questions("java");
40 | final CompletableFuture scala = questions("scala");
41 |
42 | final CompletableFuture both = java.
43 | applyToEither(scala, String::toUpperCase);
44 |
45 | both.thenAccept(title -> log.debug("First: {}", title));
46 | }
47 |
48 |
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/src/test/java/com/nurkiewicz/java8/J26_AllAnyTest.java:
--------------------------------------------------------------------------------
1 | package com.nurkiewicz.java8;
2 |
3 | import com.nurkiewicz.java8.util.AbstractFuturesTest;
4 | import org.junit.Ignore;
5 | import org.junit.Test;
6 | import org.slf4j.Logger;
7 | import org.slf4j.LoggerFactory;
8 |
9 | import java.util.concurrent.CompletableFuture;
10 | import java.util.concurrent.ExecutionException;
11 |
12 | @Ignore
13 | public class J26_AllAnyTest extends AbstractFuturesTest {
14 |
15 | private static final Logger log = LoggerFactory.getLogger(J26_AllAnyTest.class);
16 |
17 | @Test
18 | public void allOf() throws Exception {
19 | final CompletableFuture java = questions("java");
20 | final CompletableFuture scala = questions("scala");
21 | final CompletableFuture clojure = questions("clojure");
22 | final CompletableFuture groovy = questions("groovy");
23 |
24 | final CompletableFuture allCompleted = CompletableFuture.allOf(
25 | java, scala, clojure, groovy
26 | );
27 |
28 | allCompleted.thenRun(() -> {
29 | try {
30 | log.debug("Loaded: {}", java.get());
31 | log.debug("Loaded: {}", scala.get());
32 | log.debug("Loaded: {}", clojure.get());
33 | log.debug("Loaded: {}", groovy.get());
34 | } catch (InterruptedException | ExecutionException e) {
35 | log.error("", e);
36 | }
37 | });
38 | }
39 |
40 | @Test
41 | public void anyOf() throws Exception {
42 | final CompletableFuture java = questions("java");
43 | final CompletableFuture scala = questions("scala");
44 | final CompletableFuture clojure = questions("clojure");
45 | final CompletableFuture groovy = questions("groovy");
46 |
47 | final CompletableFuture