├── .gitignore ├── Cheatsheet.pdf ├── Licence.txt ├── Readme.md ├── files ├── Sonnet.txt ├── movies │ └── movies-mpaa.txt.gz ├── people.txt └── shakespeare │ ├── ospd.txt.gz │ └── words.shakespeare.txt.gz ├── images ├── 01_select-branch.png ├── 02_select-Java9-Eclipse.png ├── 03_check-branch.png ├── 04_download-zip.png └── eclipseHierarchical.png ├── pom.xml └── src ├── solutions └── java │ └── org │ └── paumard │ └── solutions │ └── codeone2019 │ ├── A_Lambdas │ ├── a_lambdas │ │ ├── A_Suppliers.java │ │ ├── B_Consumers.java │ │ ├── C_Predicates.java │ │ ├── D_Functions.java │ │ ├── E_Runnables.java │ │ └── util │ │ │ └── CircleFactory.java │ └── b_comparators │ │ └── F_Comparators.java │ ├── B_Collections │ ├── G_Iterables.java │ ├── H_Collections.java │ └── I_Lists.java │ ├── C_Maps │ └── J_Maps.java │ ├── D_Streams │ ├── K_SimpleStreams.java │ ├── L_HarderStreams.java │ ├── M_Reductions.java │ └── N_Challenges.java │ ├── E_Collectors │ ├── O_SimpleCollectors.java │ └── P_HarderCollectors.java │ └── F_Challenges │ ├── ActorsAndMoviesChallenge.java │ └── ShakespeareChallenge.java └── test └── java └── org └── paumard └── codeone2019 ├── A_Lambdas ├── a_lambdas │ ├── A_Suppliers.java │ ├── B_Consumers.java │ ├── C_Predicates.java │ ├── D_Functions.java │ ├── E_Runnables.java │ ├── model │ │ └── Circle.java │ └── util │ │ └── CircleFactory.java └── b_comparators │ ├── F_Comparators.java │ └── model │ └── Person.java ├── B_Collections ├── G_Iterables.java ├── H_Collections.java └── I_Lists.java ├── C_Maps └── J_Maps.java ├── D_Streams ├── K_SimpleStreams.java ├── L_HarderStreams.java ├── M_Reductions.java ├── N_Challenges.java └── model │ └── Person.java ├── E_Collectors ├── O_SimpleCollectors.java └── P_HarderCollectors.java └── F_Challenges ├── ActorsAndMoviesChallenge.java ├── ShakespeareChallenge.java └── model ├── Actor.java └── Movie.java /.gitignore: -------------------------------------------------------------------------------- 1 | images/*-full.png 2 | images/*.xcf 3 | .idea/ 4 | **/*.iml 5 | **/target/ 6 | *.bat -------------------------------------------------------------------------------- /Cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePaumard/code-one-2019-lambda-stream-collector-lab/2859ba7edff26d5fb0f8ef4167d8a766ce5e7a28/Cheatsheet.pdf -------------------------------------------------------------------------------- /Licence.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | ### Oracle Code One 2019 Lambda Stream Collector Lab 2 | 3 | #### Introduction 4 | 5 | Welcome to the Lambda/Streams Programming Laboratory! The goal of this lab is for you to learn about the lambda expressions, default methods, and APIs (particularly the Streams library) introduced in Java 8. 6 | 7 | You are are currently on the ***Master*** branch on this repository. This repository contains branches for each version of Java from 8 to 12, and for two IDEs: Eclipse and IntelliJ. 8 | 9 | #### Choosing the right branch and downloading the lab 10 | 11 | 0. The first thing you need to do is to choose the right branch that corresponds to your Java installation and your IDE. For that, you need to click on the `Branch` button on the GitHub interface. 12 | 13 | ![](images/01_select-branch.png) 14 | 15 | 1. And then choose the branch you need from the drop down list. On this example we are choosing Java 9 and Eclipse. 16 | 17 | ![](images/02_select-Java9-Eclipse.png) 18 | 19 | 2. From here, you should check the `Branch` button and make sure that you have selected the right one. 20 | 21 | ![](images/03_check-branch.png) 22 | 23 | 3. All you need to do now is download a ZIP file for that branch, by clicking the `Clone or download` green button that will contain the right version of the lab for you. 24 | 25 | ![](images/04_download-zip.png) 26 | 27 | 28 | #### Importing the lab in Eclipse 29 | 30 | 0. Unzip the ZIP file for the project. 31 | 32 | 1. Open Eclipse. Select `Preferences | Java | Editor | Folding`. 33 | 34 | Ensure that the `Comments` checkbox is ticked. This ensures that the hints we put with the exercises will be closed by default when you open an exercise file. 35 | 36 | Ensure that the Project Explorer or Package Explorer view property `Package Presentation` is set to `Hierarchical`, as shown below: 37 | 38 | ![](images/eclipseHierarchical.png) 39 | 40 | 2. Select `File | Import... | Maven | Existing Maven Projects`, click 41 | `Next`, select the directory where you unzipped the lab and click `Finish`. 42 | 43 | 3. Make sure Eclipse selected the right version of the JDK for your lab to work properly. 44 | 45 | 4. Maven declares two dependencies: JUnit and AssertJ. Just make sure that your configuration allows for the downloading of them. 46 | 47 | 48 | #### Importing the lab in IntelliJ 49 | 50 | 0. Unzip the ZIP file for the project. 51 | 52 | 1. Open IntelliJ. Select `File | Settings...` and look for the `Custom folding regions` property. Ensure it is ticked. This ensures that the hints we put with the exercises will be closed by default when you open an exercise file. 53 | 54 | 2. Select `File | New | Project from existing sources...`, select the directory where you unzipped the lab and click `Ok`. 55 | 56 | 3. IntelliJ will then take you through the Maven import process until the project is correctly configured. 57 | 58 | 4. Make sure IntelliJ selected the right version of the JDK for your lab to work properly. 59 | 60 | 5. Maven declares two dependencies: JUnit and AssertJ. Just make sure that your configuration allows for the downloading of them. 61 | 62 | 63 | #### Some more instructions 64 | 65 | The lab is almost the same on all the branches. Several questions have been removed from the Java 8 branch, since they rely on API added in Java 9 or later. 66 | 67 | At the top of each exercise is a comment that describes the goal of the exercise. Within the test method, there is a `// TODO` comment that marks the location where you need fill in some implementation code. There may be some setup code above the `// TODO` comment, and there will be some assertion-checking code below. You shouldn't have to modify any of the setup code at the top of the test method or the assertions at the bottom of the test method. 68 | 69 | For instance, here is the first method of the first test class `A_Suppliers`: 70 | 71 | ```Java 72 | @Test 73 | @Ignore 74 | public void a_supplier01() { 75 | Supplier sup = null; // TODO 76 | assertThat(sup.get().toString()).isEqualTo("abc"); 77 | } 78 | ``` 79 | 80 | The first thing you need to do to run the test is to remove the `@Ignore` annotation so that the test will be run. If you run it as it is, it will be red. 81 | 82 | Then you need to modify the line where the `// TODO` mark is found so that the test becomes green. In this very simple case, you can write the following: 83 | 84 | ```Java 85 | @Test 86 | public void a_supplier01() { 87 | Supplier sup = () -> new StringBuilder("abc"); 88 | assertThat(sup.get().toString()).isEqualTo("abc"); 89 | } 90 | ``` 91 | 92 | If you run this test it should be green, so you can move to the next one. 93 | 94 | There is sometimes a hint or two after a test method. If you're having trouble with an exercise, look for hints. The hint text is inside a editor fold that is closed by default, so click on the plus-sign in the left margin to read it. 95 | 96 | 97 | You should check the PDF file called `Cheatsheet.pdf` for the useful information it contains about the patterns, classes and methods you are going to need in this lab. Ultimately, you should check the Javadoc. 98 | 99 | You will find the following content in the `test/java` folder: 100 | 101 | 1. A `A_Lambdas` package 102 | 2. A `B_Collections` package 103 | 3. A `C_Maps` package 104 | 4. A `D_Streams` package 105 | 5. A `E_Collectors` package 106 | 6. A `F_Challenges` package 107 | 108 | Each package is then divided into subpackages and classes so that you can easily find your way in the lab. The difficulty is increasing from beginner level to challenge level in each package. If the first questions are too easy for you, just jump to the end and to try the challenges! 109 | 110 | The intent of the exercises is to solve them using the Java 8 lambda expressions feature, the Java 8 default methods feature, the Java 8 Streams API, and other APIs added in Java 8. Of course, it is possible to use conventional Java code, such as for-loops, but all of the exercises are amenable to being solved using new features in just a handful of lines. Most exercises will take less than half a dozen lines. Some of the more difficult exercises may take up to eight lines, depending upon how aggressive you are about breaking lines. None of the exercises involve writing large amounts of code. Most of the streams-based exercises involve writing a single stream pipeline. 111 | 112 | Several of the exercises read data from a text file. The field named "reader" is a `BufferedReader` which will be opened for you on the text file. In any exercise that refers to reading from the text file, you can simply use the "reader" variable without worry about opening or closing it. This is set up by JUnit using the `@Before` and `@After` methods at the bottom of the file. The text files you need are provided with the project. 113 | 114 | If you're really stuck, the solutions to the exercises are in the folder `src/solutions/java`. You can run them by declaring this folder as a source folder in your IDE. 115 | 116 | There is one solutions file corresponding to each exercise file. Many exercises can be solved in several different ways. In some cases, the solutions file will have several alternatives. Even if you've solved an exercise, it can be useful to look at the solutions to compare your solutions with those of the lab authors. 117 | 118 | Depending on the branch you are looking at, there are up to 126 exercises in the lab, enough to keep you busy for several hours. Good luck! -------------------------------------------------------------------------------- /files/Sonnet.txt: -------------------------------------------------------------------------------- 1 | From fairest creatures we desire increase, 2 | That thereby beauty's rose might never die, 3 | But as the riper should by time decease, 4 | His tender heir might bear his memory: 5 | But thou contracted to thine own bright eyes, 6 | Feed'st thy light's flame with self-substantial fuel, 7 | Making a famine where abundance lies, 8 | Thy self thy foe, to thy sweet self too cruel: 9 | Thou that art now the world's fresh ornament, 10 | And only herald to the gaudy spring, 11 | Within thine own bud buriest thy content, 12 | And, tender churl, mak'st waste in niggarding: 13 | Pity the world, or else this glutton be, 14 | To eat the world's due, by the grave and thee. 15 | -------------------------------------------------------------------------------- /files/movies/movies-mpaa.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePaumard/code-one-2019-lambda-stream-collector-lab/2859ba7edff26d5fb0f8ef4167d8a766ce5e7a28/files/movies/movies-mpaa.txt.gz -------------------------------------------------------------------------------- /files/people.txt: -------------------------------------------------------------------------------- 1 | # name age 2 | Mary 23 3 | James 28 4 | Patricia 23 5 | John 26 6 | Jennifer 27 7 | Robert 26 8 | Linda 25 9 | Michael 27 10 | Elizabeth 28 11 | William 24 12 | Barbara 23 13 | David 27 14 | Susan 23 15 | Richard 25 16 | Jessica 28 17 | Joseph 27 18 | Sarah 24 19 | Thomas 24 20 | Margaret 26 21 | Charles 27 -------------------------------------------------------------------------------- /files/shakespeare/ospd.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePaumard/code-one-2019-lambda-stream-collector-lab/2859ba7edff26d5fb0f8ef4167d8a766ce5e7a28/files/shakespeare/ospd.txt.gz -------------------------------------------------------------------------------- /files/shakespeare/words.shakespeare.txt.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePaumard/code-one-2019-lambda-stream-collector-lab/2859ba7edff26d5fb0f8ef4167d8a766ce5e7a28/files/shakespeare/words.shakespeare.txt.gz -------------------------------------------------------------------------------- /images/01_select-branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePaumard/code-one-2019-lambda-stream-collector-lab/2859ba7edff26d5fb0f8ef4167d8a766ce5e7a28/images/01_select-branch.png -------------------------------------------------------------------------------- /images/02_select-Java9-Eclipse.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePaumard/code-one-2019-lambda-stream-collector-lab/2859ba7edff26d5fb0f8ef4167d8a766ce5e7a28/images/02_select-Java9-Eclipse.png -------------------------------------------------------------------------------- /images/03_check-branch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePaumard/code-one-2019-lambda-stream-collector-lab/2859ba7edff26d5fb0f8ef4167d8a766ce5e7a28/images/03_check-branch.png -------------------------------------------------------------------------------- /images/04_download-zip.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePaumard/code-one-2019-lambda-stream-collector-lab/2859ba7edff26d5fb0f8ef4167d8a766ce5e7a28/images/04_download-zip.png -------------------------------------------------------------------------------- /images/eclipseHierarchical.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/JosePaumard/code-one-2019-lambda-stream-collector-lab/2859ba7edff26d5fb0f8ef4167d8a766ce5e7a28/images/eclipseHierarchical.png -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 4.0.0 7 | 8 | org.paumard 9 | code-one-2019-lambda-stream-collector-lab 10 | 1.0-SNAPSHOT 11 | 12 | 13 | 12 14 | 12 15 | 16 | 17 | 18 | 19 | 20 | junit 21 | junit 22 | 4.12 23 | test 24 | 25 | 26 | 27 | org.assertj 28 | assertj-core 29 | 3.13.2 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/A_Lambdas/a_lambdas/A_Suppliers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.paumard.solutions.codeone2019.A_Lambdas.a_lambdas.util.CircleFactory; 20 | import org.junit.Test; 21 | import org.paumard.codeone2019.A_Lambdas.a_lambdas.model.Circle; 22 | 23 | import java.util.List; 24 | import java.util.function.Supplier; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * This set of exercises covers the Supplier interface. 30 | */ 31 | public class A_Suppliers { 32 | 33 | /** 34 | * Write a lambda expression that returns a new StringBuilder 35 | * containing the string "abc". 36 | */ 37 | @Test 38 | public void a_supplier01() { 39 | 40 | Supplier sup = () -> new StringBuilder("abc"); 41 | 42 | assertThat(sup.get().toString()).isEqualTo("abc"); 43 | } 44 | 45 | /** 46 | * Write a lambda expression that returns a new, empty StringBuilder. 47 | * Try to write it using a method reference. 48 | */ 49 | @Test 50 | public void a_supplier02() { 51 | 52 | Supplier sup = StringBuilder::new; 53 | 54 | assertThat(sup.get().toString()).isEqualTo(""); 55 | } 56 | 57 | /** 58 | * Write a lambda expression that returns a new Circle. 59 | * The Circle class is provided in the model package. 60 | */ 61 | @Test 62 | public void a_supplier03() { 63 | 64 | Supplier sup = Circle::new; 65 | 66 | assertThat(sup.get().toString()).isEqualTo("Circle{color=White}"); 67 | } 68 | 69 | /** 70 | * Use the provided CircleFactory interface, that extends Supplier<Circle>. 71 | * Add a method to this interface that can create a list of three circles. 72 | */ 73 | @Test 74 | public void a_supplier04() { 75 | 76 | CircleFactory circleFactory = Circle::new; 77 | 78 | List circles = circleFactory.getThree(); 79 | 80 | assertThat(circles).containsExactly(new Circle(), new Circle(), new Circle()); 81 | } 82 | 83 | /** 84 | * Use the provided CircleFactory interface, that extends Supplier<Circle>. 85 | * Use the previous method from a_supplier04() that can create a list of three circles, 86 | * and check that it does create a list of three red circles. 87 | */ 88 | @Test 89 | public void a_supplier05() { 90 | 91 | CircleFactory circleFactory = () -> new Circle("Red"); 92 | 93 | List circles = circleFactory.getThree(); 94 | 95 | assertThat(circles).containsExactly(new Circle("Red"), new Circle("Red"), new Circle("Red")); 96 | } 97 | 98 | /** 99 | * Writing our factory in that way is not very nice. We would like to create a factor method 100 | * to create a CircleFactory, and be able to call in that way: 101 | *

102 | * CircleFactory factory = CircleFactory.createFactory(Circle::new); 103 | * In that case, the factory should be a factory of white circles. 104 | */ 105 | @Test 106 | public void a_supplier06() { 107 | 108 | CircleFactory circleFactory = CircleFactory.createFactory(Circle::new); 109 | 110 | List circles = circleFactory.getThree(); 111 | 112 | assertThat(circles).containsExactly(new Circle("White"), new Circle("White"), new Circle("White")); 113 | } 114 | 115 | /** 116 | * And what about creating a factory of colored Circle in that way: 117 | *

118 | * CircleFactory factory = CircleFactory.createFactory(Circle::new, "Blue"); 119 | * It needs another createFactory() method with two arguments. 120 | */ 121 | @Test 122 | public void a_supplier07() { 123 | 124 | CircleFactory circleFactory = CircleFactory.createFactory(Circle::new, "Blue"); 125 | 126 | List circles = circleFactory.getThree(); 127 | 128 | assertThat(circles).containsExactly(new Circle("Blue"), new Circle("Blue"), new Circle("Blue")); 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/A_Lambdas/a_lambdas/B_Consumers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.*; 22 | import java.util.function.BiConsumer; 23 | import java.util.function.Consumer; 24 | 25 | import static org.assertj.core.api.Assertions.assertThat; 26 | import static org.junit.Assert.assertTrue; 27 | 28 | /** 29 | * This set of exercises covers the Consumer and BiConsumer interfaces. 30 | * Some exercises also cover consumer chaining. 31 | */ 32 | public class B_Consumers { 33 | 34 | /** 35 | * Write a lambda expression that clears the given list. 36 | * Try to write this lambda using a method reference. 37 | */ 38 | @Test 39 | public void b_consumer01() { 40 | 41 | Consumer> cons = List::clear; 42 | 43 | List list = new ArrayList<>(Arrays.asList("a", "b", "c")); 44 | cons.accept(list); 45 | assertTrue(list.isEmpty()); 46 | } 47 | 48 | /** 49 | * Write a lambda expression that appends the 50 | * string ")" to the given StringBuilder. 51 | */ 52 | @Test 53 | public void b_consumer02() { 54 | 55 | Consumer cons = sb -> sb.append(')'); 56 | 57 | StringBuilder sb = new StringBuilder("Hello"); 58 | cons.accept(sb); 59 | assertThat(sb.toString()).isEqualTo("Hello)"); 60 | } 61 | 62 | /** 63 | * Write a lambda expression that adds the 64 | * string "(" as the first element of the given StringBuilder. 65 | */ 66 | @Test 67 | public void b_consumer03() { 68 | 69 | Consumer cons = sb -> sb.insert(0, '('); 70 | 71 | StringBuilder sb = new StringBuilder("Hello"); 72 | cons.accept(sb); 73 | assertThat(sb.toString()).isEqualTo("(Hello"); 74 | } 75 | 76 | /** 77 | * Write a lambda expression that adds the 78 | * string "(" as the first element of the given StringBuilder 79 | * and the string ")" as the last element of the given StringBuilder. 80 | * Try to use the consumers written for b_consumer2() 81 | * and b_consumer3() 82 | */ 83 | @Test 84 | public void b_consumer04() { 85 | 86 | Consumer cons03 = sb -> sb.append(')'); 87 | Consumer cons04 = sb -> sb.insert(0, '('); 88 | 89 | Consumer cons = cons03.andThen(cons04); 90 | 91 | StringBuilder sb = new StringBuilder("Hello"); 92 | cons.accept(sb); 93 | assertThat(sb.toString()).isEqualTo("(Hello)"); 94 | } 95 | 96 | /** 97 | * Write a lambda expression that adds the given string to the 98 | * given list. Try to write this lambda as a method reference. 99 | */ 100 | @Test 101 | public void b_consumer05() { 102 | 103 | List strings = new ArrayList<>(Arrays.asList("one", "two", "three")); 104 | 105 | BiConsumer, String> bicons = List::add; 106 | bicons.accept(strings, "four"); 107 | 108 | assertThat(strings).containsExactly("one", "two", "three", "four"); 109 | } 110 | 111 | /** 112 | * Write a lambda expression that adds the given key and value to the 113 | * map. Try to write this lambda as a method reference. 114 | */ 115 | @Test 116 | public void b_consumer06() { 117 | 118 | Map map = new HashMap<>(); 119 | map.put(1, "one"); 120 | map.put(2, "two"); 121 | map.put(3, "three"); 122 | 123 | BiConsumer bicons = map::put; 124 | bicons.accept(4, "four"); 125 | 126 | assertThat(map).containsKeys(1, 2, 3, 4); 127 | assertThat(map.get(4)).isEqualTo("four"); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/A_Lambdas/a_lambdas/C_Predicates.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Objects; 22 | import java.util.function.Predicate; 23 | 24 | import static org.junit.Assert.assertFalse; 25 | import static org.junit.Assert.assertTrue; 26 | 27 | /** 28 | * This set of exercises covers the Predicate interface. 29 | * Some exercises also cover predicate chaining. 30 | */ 31 | public class C_Predicates { 32 | 33 | /** 34 | * Write a lambda expression that is a predicate 35 | * that tests whether a string null. 36 | * Try to write this lambda using a method reference. 37 | */ 38 | @Test 39 | public void c_predicate01() { 40 | 41 | Predicate pred = Objects::isNull; 42 | 43 | assertTrue(pred.test(null)); 44 | assertFalse(pred.test("")); 45 | } 46 | 47 | /** 48 | * Write a lambda expression that is a predicate 49 | * that tests whether a string is empty. 50 | * Try to write this lambda using a method reference. 51 | */ 52 | @Test 53 | public void c_predicate02() { 54 | 55 | Predicate pred = String::isEmpty; 56 | 57 | assertTrue(pred.test("")); 58 | assertFalse(pred.test("a")); 59 | } 60 | 61 | /** 62 | * Create a predicate that returns true when the given String 63 | * is non-null. Try to use the predicate you wrote 64 | * for c_predicate1() 65 | */ 66 | @Test 67 | public void c_predicate03() { 68 | 69 | Predicate pred01 = Objects::isNull; 70 | 71 | Predicate pred = pred01.negate(); 72 | 73 | assertTrue(pred.test("")); 74 | assertFalse(pred.test(null)); 75 | } 76 | 77 | /** 78 | * Create a predicate that returns true when the given String 79 | * is null or empty. Try to use the predicates you wrote 80 | * for c_predicate1() c_predicate2() 81 | */ 82 | @Test 83 | public void c_predicate04() { 84 | 85 | Predicate pred01 = Objects::isNull; 86 | Predicate pred02 = String::isEmpty; 87 | 88 | Predicate pred = pred01.or(pred02); 89 | 90 | assertTrue(pred.test("")); 91 | assertTrue(pred.test(null)); 92 | assertFalse(pred.test("Hello")); 93 | } 94 | 95 | /** 96 | * Create a predicate that returns true when the given String 97 | * is non-null and non-empty. You can use the predicates you 98 | * wrote for c_predicate1() c_predicate2() or the one 99 | * you wrote for c_predicate4() 100 | */ 101 | @Test 102 | public void c_predicate05() { 103 | 104 | Predicate pred01 = Objects::isNull; 105 | Predicate pred02 = String::isEmpty; 106 | 107 | Predicate pred = pred01.or(pred02).negate(); 108 | 109 | assertFalse(pred.test("")); 110 | assertFalse(pred.test(null)); 111 | assertTrue(pred.test("Hello")); 112 | } 113 | 114 | /** 115 | * Write a lambda expression that is a predicate 116 | * that tests whether a string is shorter than four characters. 117 | */ 118 | @Test 119 | public void c_predicate06() { 120 | 121 | Predicate pred = s -> s.length() < 4; 122 | 123 | assertTrue(pred.test("abc")); 124 | assertFalse(pred.test("abcd")); 125 | assertFalse(pred.test("abcde")); 126 | } 127 | 128 | /** 129 | * Create a predicate that is true if the provided string equals ERROR. 130 | * Try writing it using a method reference. 131 | */ 132 | @Test 133 | public void c_predicate07() { 134 | 135 | Predicate equalsError = "ERROR"::equals; 136 | 137 | assertFalse(equalsError.test("Hello")); 138 | assertTrue(equalsError.test("ERROR")); 139 | assertFalse(equalsError.test(null)); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/A_Lambdas/a_lambdas/D_Functions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.function.BiFunction; 22 | import java.util.function.Function; 23 | 24 | import static org.assertj.core.api.Assertions.assertThat; 25 | 26 | /** 27 | * This set of exercises covers the Function interface. 28 | * Some exercises also cover function chaining and composition. 29 | */ 30 | public class D_Functions { 31 | 32 | /** 33 | * Write a lambda expression that converts the 34 | * given string to upper case. Try to write this lambda 35 | * as a method reference. 36 | */ 37 | @Test 38 | public void d_function01() { 39 | 40 | Function func = String::toUpperCase; 41 | 42 | assertThat(func.apply("abc")).isEqualTo("ABC"); 43 | } 44 | 45 | /** 46 | * Write a lambda expression that wraps the given 47 | * string in parentheses. 48 | */ 49 | @Test 50 | public void d_function02() { 51 | 52 | Function func = s -> "(" + s + ")"; 53 | 54 | assertThat(func.apply("abc")).isEqualTo("(abc)"); 55 | } 56 | 57 | /** 58 | * Write a lambda expression that returns the length of the 59 | * given String. Try to write this lambda as a method reference. 60 | */ 61 | @Test 62 | public void d_function03() { 63 | 64 | Function func = String::length; 65 | 66 | assertThat(func.apply("")).isEqualTo(0); 67 | assertThat(func.apply("Hello!")).isEqualTo(6); 68 | } 69 | 70 | /** 71 | * Write a lambda expression that returns an empty String 72 | * if the given string is null, and the given string otherwise. 73 | */ 74 | @Test 75 | public void d_function04() { 76 | 77 | Function func = s -> s == null ? "" : s; 78 | 79 | assertThat(func.apply(null)).isEqualTo(""); 80 | assertThat(func.apply("")).isEqualTo(""); 81 | assertThat(func.apply("Hello")).isEqualTo("Hello"); 82 | } 83 | 84 | /** 85 | * Write a lambda expression that returns the length of the given 86 | * String if it is not null, and 0 if the given String is null. 87 | * Try using the a_lambdas written in d_function3() and d_function4() 88 | */ 89 | @Test 90 | public void d_function05() { 91 | 92 | Function func03 = String::length; 93 | Function func04 = s -> s == null ? "" : s; 94 | 95 | Function func = func03.compose(func04); 96 | // you can also call func04.andThen(func03) 97 | 98 | assertThat(func.apply(null)).isEqualTo(0); 99 | assertThat(func.apply("")).isEqualTo(0); 100 | assertThat(func.apply("Hello")).isEqualTo(5); 101 | } 102 | 103 | /** 104 | * Write a lambda expression that, given two strings, returns the result 105 | * of concatenating the first with the second, followed by the 106 | * first again. 107 | */ 108 | @Test 109 | public void d_function06() { 110 | 111 | BiFunction bifunc = (s1, s2) -> s1 + s2 + s1; 112 | 113 | assertThat(bifunc.apply("-", "Hello")).isEqualTo("-Hello-"); 114 | } 115 | 116 | /** 117 | * Write a lambda expression that returns the index of 118 | * the first occurrence of the second string within the first string, 119 | * or -1 if the second string doesn't occur within the first string. 120 | * Try to write this lambda using a method reference. 121 | */ 122 | @Test 123 | public void d_function07() { 124 | 125 | BiFunction bifunc = String::indexOf; 126 | 127 | assertThat(bifunc.apply("Hello world", "Hello")).isEqualTo(0); 128 | assertThat(bifunc.apply("Hello world", "world")).isEqualTo(6); 129 | } 130 | 131 | /** 132 | * Write a lambda expression that returns the index of 133 | * the first occurrence of the given string within the string 134 | * "Hello world", or -1 if the given string is not found. 135 | * Try to write this lambda using a method reference. 136 | */ 137 | @Test 138 | public void d_function08() { 139 | 140 | String pattern = "Hello world!"; 141 | Function func = pattern::indexOf; 142 | 143 | assertThat(func.apply("Hello")).isEqualTo(0); 144 | assertThat(func.apply("world")).isEqualTo(6); 145 | } 146 | 147 | /** 148 | * Write a lambda expression that returns the index of 149 | * the first occurrence of the given string within the string 150 | * "Hello world", or -1 if the given string is not found. 151 | * Try to write this lambda as a partial application of the 152 | * lambda you wrote in d_function07(). 153 | */ 154 | @Test 155 | public void d_function09() { 156 | 157 | BiFunction bifunc07 = String::indexOf; 158 | 159 | String pattern = "Hello world!"; 160 | 161 | Function func = s -> bifunc07.apply(pattern, s); 162 | 163 | assertThat(func.apply("Hello")).isEqualTo(0); 164 | assertThat(func.apply("world")).isEqualTo(6); 165 | } 166 | 167 | } 168 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/A_Lambdas/a_lambdas/E_Runnables.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.assertj.core.api.Assertions; 20 | import org.junit.Test; 21 | 22 | /** 23 | * This set of exercises covers the Runnable interface. 24 | */ 25 | public class E_Runnables { 26 | 27 | /** 28 | * Write a lambda expression that appends the string suffix 29 | * to the sb variable (a StringBuilder). 30 | */ 31 | @Test 32 | public void e_runnable01() { 33 | 34 | StringBuilder sb = new StringBuilder("abc"); 35 | String suffix = "--"; 36 | 37 | Runnable r = () -> sb.append(suffix); 38 | 39 | r.run(); 40 | r.run(); 41 | r.run(); 42 | Assertions.assertThat(sb.toString()).isEqualTo("abc------"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/A_Lambdas/a_lambdas/util/CircleFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.A_Lambdas.a_lambdas.util; 18 | 19 | import org.paumard.codeone2019.A_Lambdas.a_lambdas.model.Circle; 20 | 21 | import java.util.List; 22 | import java.util.function.Function; 23 | import java.util.function.Supplier; 24 | import java.util.stream.Collectors; 25 | import java.util.stream.IntStream; 26 | 27 | public interface CircleFactory extends Supplier { 28 | 29 | 30 | default List getThree() { 31 | return IntStream.range(0, 3).mapToObj(index -> get()).collect(Collectors.toList()); 32 | } 33 | 34 | static CircleFactory createFactory(Supplier circleSupplier) { 35 | return circleSupplier::get; 36 | } 37 | 38 | static CircleFactory createFactory(Function constructor, String color) { 39 | return () -> constructor.apply(color); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/A_Lambdas/b_comparators/F_Comparators.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.A_Lambdas.b_comparators; 18 | 19 | import org.junit.Test; 20 | import org.paumard.codeone2019.A_Lambdas.b_comparators.model.Person; 21 | 22 | import java.util.Comparator; 23 | import java.util.function.IntBinaryOperator; 24 | 25 | import static java.util.Comparator.naturalOrder; 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * This set of exercises covers the Comparator interface. 30 | * Comparator chaining and factory methods are also covered.The code you need 31 | * to write uses the factory methods and default methods of the Comparator interface. 32 | */ 33 | public class F_Comparators { 34 | 35 | final Person michael = new Person("Michael", "Jackson", 51); 36 | final Person rod = new Person("Rod", "Stewart", 71); 37 | final Person paul = new Person("Paul", "McCartney", 74); 38 | final Person mick = new Person("Mick", "Jagger", 73); 39 | final Person jermaine = new Person("Jermaine", "Jackson", 61); 40 | 41 | /** 42 | * Write a Comparator that compare instances of String using their length. 43 | * For instance FOUR (4 letters) is greater than TWO (three letters) 44 | */ 45 | @Test 46 | public void f_comparator01() { 47 | 48 | Comparator compareByLength = Comparator.comparing(String::length); 49 | 50 | assertThat(compareByLength.compare("FOUR", "TWO")).isGreaterThan(0); 51 | assertThat(compareByLength.compare("ONE", "SEVEN")).isLessThan(0); 52 | assertThat(compareByLength.compare("ONE", "TWO")).isEqualTo(0); 53 | } 54 | 55 | /** 56 | * Write a Comparator that compare instances of String using their length. 57 | * If the lengths are the same, then use the alphabetical order. 58 | */ 59 | @Test 60 | public void f_comparator02() { 61 | 62 | Comparator compareByLengthThenAlphabetical = 63 | Comparator.comparing(String::length).thenComparing(naturalOrder()); 64 | 65 | assertThat(compareByLengthThenAlphabetical.compare("FOUR", "TWO")).isGreaterThan(0); 66 | assertThat(compareByLengthThenAlphabetical.compare("ONE", "SEVEN")).isLessThan(0); 67 | assertThat(compareByLengthThenAlphabetical.compare("ONE", "TWO")).isLessThan(0); 68 | assertThat(compareByLengthThenAlphabetical.compare("FOUR", "FIVE")).isGreaterThan(0); 69 | assertThat(compareByLengthThenAlphabetical.compare("EIGHT", "EIGHT")).isEqualTo(0); 70 | } 71 | 72 | /** 73 | * Write a Comparator that compares instances of Person using their lastName. 74 | */ 75 | @Test 76 | public void f_comparator03() { 77 | 78 | Comparator compareByLastName = Comparator.comparing(Person::getLastName); 79 | 80 | assertThat(compareByLastName.compare(michael, rod)).isLessThan(0); 81 | assertThat(compareByLastName.compare(paul, paul)).isEqualTo(0); 82 | assertThat(compareByLastName.compare(michael, jermaine)).isEqualTo(0); 83 | } 84 | 85 | /** 86 | * Write a Comparator that compares instances of Person using their 87 | * lastName, and if their last name is the same, uses their first name. 88 | */ 89 | @Test 90 | public void f_comparator04() { 91 | 92 | Comparator compareByLastNameThenFirstName = 93 | Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName); 94 | 95 | assertThat(compareByLastNameThenFirstName.compare(michael, rod)).isLessThan(0); 96 | assertThat(compareByLastNameThenFirstName.compare(paul, paul)).isEqualTo(0); 97 | assertThat(compareByLastNameThenFirstName.compare(michael, jermaine)).isGreaterThan(0); 98 | } 99 | 100 | /** 101 | * Write a Comparator that compares the people in the order reversed from 102 | * the one you wrote in the comparator04() exercise. 103 | */ 104 | @Test 105 | public void f_comparator05() { 106 | 107 | Comparator compareByLastNameThenFirstName = 108 | Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName); 109 | 110 | Comparator compareByLastNameThenFirstNameReversed = compareByLastNameThenFirstName.reversed(); 111 | 112 | assertThat(compareByLastNameThenFirstNameReversed.compare(michael, rod)).isGreaterThan(0); 113 | assertThat(compareByLastNameThenFirstNameReversed.compare(paul, paul)).isEqualTo(0); 114 | assertThat(compareByLastNameThenFirstNameReversed.compare(michael, jermaine)).isLessThan(0); 115 | } 116 | 117 | /** 118 | * Write a Comparator that compares the people in the same order than the 119 | * one you wrote in comparator04(), but that supports null values. The null 120 | * values should be considered greater than any non-null values. 121 | */ 122 | @Test 123 | public void f_comparator06() { 124 | 125 | Comparator compareByLastNameThenFirstName = 126 | Comparator.comparing(Person::getLastName).thenComparing(Person::getFirstName); 127 | 128 | Comparator compareByLastNameThenFirstNameWithNull = 129 | Comparator.nullsLast(compareByLastNameThenFirstName); 130 | 131 | assertThat(compareByLastNameThenFirstNameWithNull.compare(michael, rod)).isLessThan(0); 132 | assertThat(compareByLastNameThenFirstNameWithNull.compare(paul, paul)).isEqualTo(0); 133 | assertThat(compareByLastNameThenFirstNameWithNull.compare(michael, jermaine) > 0); 134 | assertThat(compareByLastNameThenFirstNameWithNull.compare(mick, null)).isLessThan(0); 135 | assertThat(compareByLastNameThenFirstNameWithNull.compare(null, mick)).isGreaterThan(0); 136 | } 137 | 138 | /** 139 | * Write a Comparator that compares two people by age. 140 | * Try to write the comparator so as to avoid boxing of primitives. 141 | */ 142 | @Test 143 | public void f_comparator07() { 144 | 145 | Comparator compareByAge = Comparator.comparingInt(Person::getAge); 146 | 147 | assertThat(compareByAge.compare(michael, rod)).isLessThan(0); 148 | assertThat(compareByAge.compare(paul, paul)).isEqualTo(0); 149 | assertThat(compareByAge.compare(mick, jermaine)).isGreaterThan(0); 150 | } 151 | 152 | /** 153 | * Write a Comparator that compares two people using the fact that the Person 154 | * class implements Comparable. Try to use a factory method from the 155 | * Comparator interface. 156 | */ 157 | @Test 158 | public void f_comparator08() { 159 | 160 | Comparator compare = Comparator.naturalOrder(); 161 | 162 | assertThat(compare.compare(michael, rod)).isLessThan(0); 163 | assertThat(compare.compare(paul, paul)).isEqualTo(0); 164 | assertThat(compare.compare(mick, jermaine)).isGreaterThan(0); 165 | assertThat(compare.compare(michael, jermaine)).isGreaterThan(0); 166 | } 167 | 168 | 169 | /** 170 | * Write a lambda expression that compares two int values and returns an 171 | * int result that is less than, equal to, or greater than zero, like 172 | * a comparator. Watch out for overflow. The Comparator interface takes 173 | * two objects, but in this case we are comparing int primitives, so the 174 | * functional interface we use is IntBinaryOperator. 175 | */ 176 | @Test 177 | public void f_comparator09() { 178 | 179 | IntBinaryOperator intCompare = (i1, i2) -> Integer.compare(i1, i2); 180 | 181 | assertThat(intCompare.applyAsInt(0, 1)).isLessThan(0); 182 | assertThat(intCompare.applyAsInt(1, 1)).isEqualTo(0); 183 | assertThat(intCompare.applyAsInt(2, 1) > 0); 184 | assertThat(intCompare.applyAsInt(Integer.MIN_VALUE, Integer.MAX_VALUE)).isLessThan(0); 185 | assertThat(intCompare.applyAsInt(Integer.MAX_VALUE, Integer.MIN_VALUE)).isGreaterThan(0); 186 | } 187 | 188 | /** 189 | * Write a method reference that compares two int values and returns an 190 | * int result that is less than, equal to, or greater than zero, like 191 | * a comparator. 192 | */ 193 | @Test 194 | public void f_comparator10() { 195 | 196 | IntBinaryOperator intCompare = Integer::compare; 197 | 198 | assertThat(intCompare.applyAsInt(0, 1)).isLessThan(0); 199 | assertThat(intCompare.applyAsInt(1, 1)).isEqualTo(0); 200 | assertThat(intCompare.applyAsInt(2, 1)).isGreaterThan(0); 201 | assertThat(intCompare.applyAsInt(Integer.MIN_VALUE, Integer.MAX_VALUE)).isLessThan(0); 202 | assertThat(intCompare.applyAsInt(Integer.MAX_VALUE, Integer.MIN_VALUE)).isGreaterThan(0); 203 | } 204 | 205 | interface DoubleToIntBiFunction { 206 | int applyAsInt(double a, double b); 207 | } 208 | 209 | /** 210 | * Write a method reference that compares two double values and returns an 211 | * int result that is less than, equal to, or greater than zero, like 212 | * a comparator. There functional interface that takes two doubles and returns 213 | * an int, so we define one here. Comparing double values introduces 214 | * special cases such NaN. Consider all NaN values to be equal to each other 215 | * and greater than any non-NaN value. 216 | */ 217 | @Test 218 | public void f_comparator11() { 219 | 220 | DoubleToIntBiFunction doubleCompare = Double::compare; 221 | 222 | assertThat(doubleCompare.applyAsInt(0.0, 1.0)).isLessThan(0); 223 | assertThat(doubleCompare.applyAsInt(1.0, 1.0)).isEqualTo(0); 224 | assertThat(doubleCompare.applyAsInt(2.0, 1.0)).isGreaterThan(0); 225 | assertThat(doubleCompare.applyAsInt(Double.NaN, Double.NaN)).isEqualTo(0); 226 | assertThat(doubleCompare.applyAsInt(Double.NaN, 0.0)).isGreaterThan(0); 227 | assertThat(doubleCompare.applyAsInt(0.0, Double.NaN)).isLessThan(0); 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/B_Collections/G_Iterables.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.B_Collections; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | import java.util.List; 23 | import java.util.stream.Collectors; 24 | 25 | import static org.assertj.core.api.Assertions.assertThat; 26 | 27 | /** 28 | * This set of exercises covers the default method added to the Iterable interface. 29 | */ 30 | public class G_Iterables { 31 | 32 | /** 33 | * Given a list of StringBuilders, modify each StringBuilder 34 | * in-place by appending the string "new" to each one. 35 | */ 36 | @Test 37 | public void g_iterable01() { 38 | 39 | List sbList = Arrays.asList( 40 | new StringBuilder("alfa"), 41 | new StringBuilder("bravo"), 42 | new StringBuilder("charlie")); 43 | 44 | sbList.forEach(stringBuilder -> stringBuilder.append("new")); 45 | 46 | List strings = sbList.stream() 47 | .map(StringBuilder::toString) 48 | .collect(Collectors.toList()); 49 | 50 | assertThat(strings).hasSize(3); 51 | assertThat(strings).contains("alfanew", "bravonew", "charlienew"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/B_Collections/H_Collections.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.B_Collections; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.ArrayList; 22 | import java.util.Arrays; 23 | import java.util.List; 24 | 25 | import static org.assertj.core.api.Assertions.assertThat; 26 | 27 | /** 28 | * This set of exercises covers the default method added to the Collection interface. 29 | */ 30 | public class H_Collections { 31 | 32 | /** 33 | * Remove the words that have odd lengths from the list. 34 | */ 35 | @Test 36 | public void h_collection01() { 37 | 38 | List list = new ArrayList<>(Arrays.asList( 39 | "alfa", "bravo", "charlie", "delta", "echo", "foxtrot")); 40 | 41 | list.removeIf(element -> element.length() % 2 == 1); 42 | 43 | assertThat(list).hasSize(2); 44 | assertThat(list).contains("alfa", "echo"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/B_Collections/I_Lists.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.B_Collections; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | import java.util.Comparator; 23 | import java.util.List; 24 | 25 | import static java.util.Comparator.naturalOrder; 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * This set of exercises covers the default method added to the List interface. 30 | */ 31 | public class I_Lists { 32 | 33 | /** 34 | * Replace every word in the list with its upper case equivalent. 35 | */ 36 | @Test 37 | public void i_list01() { 38 | 39 | List strings = Arrays.asList( 40 | "alfa", "bravo", "charlie", "delta", "echo", "foxtrot"); 41 | 42 | strings.replaceAll(String::toUpperCase); 43 | 44 | assertThat(strings).containsExactly("ALFA", "BRAVO", "CHARLIE", "DELTA", "ECHO", "FOXTROT"); 45 | } 46 | 47 | /** 48 | * Replace every null value in the list with an empty String. 49 | */ 50 | @Test 51 | public void i_list02() { 52 | 53 | List strings = Arrays.asList( 54 | "alfa", null, "charlie", "delta", null, "foxtrot"); 55 | 56 | strings.replaceAll(s -> s == null ? "" : s); 57 | 58 | assertThat(strings).containsExactly("alfa", "", "charlie", "delta", "", "foxtrot"); 59 | } 60 | 61 | /** 62 | * Sort the content of the list in the alphabetical order of the strings. 63 | * Try to use a factory method from Comparator. 64 | */ 65 | @Test 66 | public void i_list03() { 67 | 68 | List strings = Arrays.asList( 69 | "one", "two", "three", "four", "five", "six"); 70 | 71 | strings.sort(naturalOrder()); 72 | 73 | assertThat(strings).containsExactly("five", "four", "one", "six", "three", "two"); 74 | } 75 | 76 | /** 77 | * Sort the content of the list by the length of the strings. In case the length is the same, 78 | * then use the alphabetical order. 79 | * Try to use a factory method from Comparator. 80 | */ 81 | @Test 82 | public void i_list04() { 83 | 84 | List strings = Arrays.asList( 85 | "one", "two", "three", "four", "five", "six"); 86 | 87 | Comparator cmp = Comparator.comparing(String::length).thenComparing(naturalOrder()); 88 | 89 | strings.sort(cmp); 90 | 91 | assertThat(strings).containsExactly("one", "six", "two", "five", "four", "three"); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/D_Streams/K_SimpleStreams.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.D_Streams; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | import java.util.List; 23 | import java.util.function.Function; 24 | import java.util.stream.Collectors; 25 | import java.util.stream.IntStream; 26 | import java.util.stream.Stream; 27 | 28 | import static org.assertj.core.api.Assertions.assertThat; 29 | 30 | /** 31 | * This set of exercises covers simple simpleStream pipelines, 32 | * including intermediate operations and basic collectors. 33 | */ 34 | public class K_SimpleStreams { 35 | 36 | /** 37 | * Given a list of words, create an output list that contains the elements 38 | * converted to upper case. 39 | * Use the collect(Collectors.toList()) pattern to create the output list. 40 | */ 41 | @Test 42 | public void k_simpleStream01() { 43 | 44 | List input = Arrays.asList( 45 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 46 | 47 | List result = input.stream().map(String::toUpperCase).collect(Collectors.toList()); 48 | 49 | assertThat(result) 50 | .containsExactly("ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN"); 51 | } 52 | 53 | /** 54 | * Given a list of words, create an output list that contains 55 | * only the odd-length words, converted to upper case. 56 | * Use the collect(Collectors.toList()) pattern to create the output list. 57 | */ 58 | @Test 59 | public void k_simpleStream02() { 60 | 61 | List input = Arrays.asList( 62 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 63 | 64 | List result = input.stream().filter(s -> s.length() % 2 == 1).map(String::toUpperCase).collect(Collectors.toList()); 65 | 66 | assertThat(result) 67 | .containsExactly("ONE", "TWO", "THREE", "SIX", "SEVEN", "EIGHT", "TEN"); 68 | } 69 | 70 | /** 71 | * Given a list of words, create an output list that contains 72 | * only words from 3 to 8. 73 | * Use the collect(Collectors.toList()) pattern to create the output list. 74 | */ 75 | @Test 76 | public void k_simpleStream03() { 77 | 78 | List input = Arrays.asList( 79 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 80 | 81 | List result = input.stream().limit(8).skip(2).collect(Collectors.toList()); 82 | 83 | assertThat(result) 84 | .containsExactly("three", "four", "five", "six", "seven", "eight"); 85 | } 86 | 87 | /** 88 | * Given a list of words, create an output list that contains 89 | * only the first letters of all the words, without any double. 90 | * Use the collect(Collectors.toList()) pattern to create the output list. 91 | */ 92 | @Test 93 | public void k_simpleStream04() { 94 | 95 | List input = Arrays.asList( 96 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 97 | 98 | List result = input.stream().map(s -> s.substring(0, 1)).distinct().collect(Collectors.toList()); 99 | 100 | assertThat(result) 101 | .containsExactly("o", "t", "f", "s", "e", "n"); 102 | } 103 | 104 | /** 105 | * Given a list of words, create an output list that contains 106 | * only the first letters of all the words, without any double, sorted in the alphabetical order. 107 | * Use the collect(Collectors.toList()) pattern to create the output list. 108 | */ 109 | @Test 110 | public void k_simpleStream05() { 111 | 112 | List input = Arrays.asList( 113 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 114 | 115 | List result = input.stream().map(s -> s.substring(0, 1)).distinct().sorted().collect(Collectors.toList()); 116 | 117 | assertThat(result) 118 | .containsExactly("e", "f", "n", "o", "s", "t"); 119 | } 120 | 121 | /** 122 | * Given a list of words, count the number of different lengths of those words. 123 | * Try not to create any list. 124 | */ 125 | @Test 126 | public void k_simpleStream06() { 127 | 128 | List input = Arrays.asList( 129 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 130 | 131 | long result = input.stream().map(String::length).distinct().count(); 132 | 133 | assertThat(result).isEqualTo(3L); 134 | } 135 | 136 | /** 137 | * Create the following list: {"+", "+", "+", "+", "+"}. 138 | * Try to use a factory method from Stream. 139 | */ 140 | @Test 141 | public void k_simpleStream07() { 142 | 143 | List result = Stream.generate(() -> "+").limit(5).collect(Collectors.toList()); 144 | 145 | assertThat(result).containsExactly("+", "+", "+", "+", "+"); 146 | } 147 | 148 | /** 149 | * Create the following list: {"+++", "++++", "+++++", "++++++", "+++++++"}. 150 | * Try to use a factory method from Stream. 151 | */ 152 | @Test 153 | public void k_simpleStream08() { 154 | 155 | List result = Stream.iterate("+", s -> s + "+").limit(7).skip(2).collect(Collectors.toList()); 156 | 157 | assertThat(result).containsExactly("+++", "++++", "+++++", "++++++", "+++++++"); 158 | } 159 | 160 | /** 161 | * Create the following list: {1, 2, 3, 4, 5}. 162 | * Try to avoid the boxing of integers until the list is created. 163 | */ 164 | @Test 165 | public void k_simpleStream09() { 166 | 167 | List result = IntStream.range(1, 6).boxed().collect(Collectors.toList()); 168 | 169 | assertThat(result).containsExactly(1, 2, 3, 4, 5); 170 | } 171 | 172 | /** 173 | * Create a function that take a String as a parameter and returns 174 | * the list of the letters of that string, in lower case, ordered in alphabetical order 175 | * and with no doubles. 176 | */ 177 | @Test 178 | public void k_simpleStream10() { 179 | 180 | // This is the Java 8 solution 181 | // Function> wordToLetters = 182 | // word -> word.chars().filter(Character::isLetter).mapToObj(letter -> (char)letter).map(String::valueOf) 183 | // .map(String::toLowerCase).distinct().sorted().collect(Collectors.toList()); 184 | 185 | // Starting with Java 11 you can write the following 186 | Function> wordToLetters = 187 | word -> word.chars().filter(Character::isLetter).mapToObj(Character::toString) 188 | .map(String::toLowerCase).distinct().sorted().collect(Collectors.toList()); 189 | 190 | assertThat(wordToLetters.apply("Hello world")).containsExactly("d", "e", "h", "l", "o", "r", "w"); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/D_Streams/L_HarderStreams.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.D_Streams; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import java.io.BufferedReader; 24 | import java.io.IOException; 25 | import java.nio.charset.StandardCharsets; 26 | import java.nio.file.Files; 27 | import java.nio.file.Paths; 28 | import java.util.Arrays; 29 | import java.util.Comparator; 30 | import java.util.List; 31 | import java.util.function.Function; 32 | import java.util.regex.Pattern; 33 | import java.util.stream.Collectors; 34 | import java.util.stream.Stream; 35 | 36 | import static java.util.Comparator.naturalOrder; 37 | import static org.assertj.core.api.Assertions.assertThat; 38 | 39 | /** 40 | * This set of exercises covers harder stream pipelines, 41 | * including intermediate operations and collectors. 42 | *

43 | * Some of these exercises use a BufferedReader variable 44 | * named "reader" that the test has set up for you. 45 | */ 46 | public class L_HarderStreams { 47 | 48 | /** 49 | * Count the number of lines in the text file. 50 | *

51 | * Remember to use the BufferedReader named "reader" that has already been 52 | * opened for you. 53 | */ 54 | @Test 55 | public void l_harderStream01() { 56 | 57 | long count = reader.lines().count(); 58 | 59 | assertThat(count).isEqualTo(14); 60 | } 61 | 62 | /** 63 | * Find the length of the longest line in the text file. 64 | *

65 | * Remember to use the BufferedReader named "reader" that has already been 66 | * opened for you. 67 | */ 68 | @Test 69 | public void l_harderStream02() { 70 | 71 | int longestLength = reader.lines().mapToInt(String::length).max().getAsInt(); 72 | 73 | assertThat(longestLength).isEqualTo(53); 74 | } 75 | 76 | /** 77 | * Find the longest line in the text file. 78 | *

79 | * Remember to use the BufferedReader named "reader" that has already been 80 | * opened for you. 81 | */ 82 | @Test 83 | public void l_harderStream03() { 84 | 85 | String longestLine = reader.lines().max(Comparator.comparing(String::length)).get(); 86 | 87 | assertThat(longestLine).isEqualTo("Feed'st thy light's flame with self-substantial fuel,"); 88 | } 89 | 90 | /** 91 | * Select one of the longest words from the input list. 92 | */ 93 | @Test 94 | public void l_harderStream04() { 95 | 96 | List input = Arrays.asList( 97 | "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"); 98 | 99 | String result = input.stream().max(Comparator.comparing(String::length)).get(); 100 | 101 | assertThat(result).isIn("charlie", "foxtrot"); 102 | } 103 | 104 | /** 105 | * Create a list of all the letters used in the following list, ordered in the alphabetical order 106 | * and with no doubles. 107 | * You can use a variant of the function created for K_SimpleStreams.simpleStream10(). 108 | */ 109 | @Test 110 | public void l_harderStream05() { 111 | 112 | List input = Arrays.asList( 113 | "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"); 114 | 115 | Function> wordToLetters = 116 | word -> word.chars().filter(Character::isLetter).mapToObj(Character::toString); 117 | 118 | List result = input.stream() 119 | .flatMap(wordToLetters) 120 | .distinct().sorted() 121 | .collect(Collectors.toList()); 122 | 123 | assertThat(result).containsExactly("a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "o", "r", "t", "v", "x"); 124 | } 125 | 126 | /** 127 | * Collect all the words from the text file into a list. 128 | *

129 | * Remember to use the BufferedReader named "reader" that has already been 130 | * opened for you. 131 | * Use the regular expression Pattern SPLIT_PATTERN to split a string into words, and use 132 | * Pattern.splitAsStream(String) to do the splitting. SPLIT_PATTERN is defined at the bottom of this file. 133 | * As before, use the BufferedReader variable named "reader" that has been set up for you to read from 134 | * the text file. 135 | */ 136 | @Test 137 | public void l_harderStream06() { 138 | 139 | List output = 140 | reader.lines() 141 | .flatMap(SPLIT_PATTERN::splitAsStream) 142 | .collect(Collectors.toList()); 143 | 144 | assertThat(output).isEqualTo( 145 | Arrays.asList( 146 | "From", "fairest", "creatures", "we", "desire", "increase", 147 | "That", "thereby", "beauty's", "rose", "might", "never", "die", 148 | "But", "as", "the", "riper", "should", "by", "time", "decease", 149 | "His", "tender", "heir", "might", "bear", "his", "memory", 150 | "But", "thou", "contracted", "to", "thine", "own", "bright", "eyes", 151 | "Feed'st", "thy", "light's", "flame", "with", "self", "substantial", "fuel", 152 | "Making", "a", "famine", "where", "abundance", "lies", 153 | "Thy", "self", "thy", "foe", "to", "thy", "sweet", "self", "too", "cruel", 154 | "Thou", "that", "art", "now", "the", "world's", "fresh", "ornament", 155 | "And", "only", "herald", "to", "the", "gaudy", "spring", 156 | "Within", "thine", "own", "bud", "buriest", "thy", "content", 157 | "And", "tender", "churl", "mak'st", "waste", "in", "niggarding", 158 | "Pity", "the", "world", "or", "else", "this", "glutton", "be", 159 | "To", "eat", "the", "world's", "due", "by", "the", "grave", "and", "thee")); 160 | } 161 | 162 | /** 163 | * Read the words from the text file, and create a list containing the words 164 | * of length 8 or longer, converted to lower case, and sorted alphabetically. 165 | *

166 | * Remember to use the BufferedReader named "reader" that has already been 167 | * opened for you. 168 | */ 169 | @Test 170 | public void l_harderStream07() { 171 | 172 | List output = 173 | reader.lines() 174 | .map(String::toLowerCase) 175 | .flatMap(SPLIT_PATTERN::splitAsStream) 176 | .filter(s -> s.length() >= 8) 177 | .distinct() 178 | .sorted() 179 | .collect(Collectors.toList()); 180 | 181 | assertThat(output).isEqualTo( 182 | Arrays.asList( 183 | "abundance", "beauty's", "contracted", "creatures", 184 | "increase", "niggarding", "ornament", "substantial")); 185 | } 186 | 187 | /** 188 | * Read the words from the text file, and create a list containing the words 189 | * of length 8 or longer, converted to lower case, and sorted reverse alphabetically. 190 | * (Same as above except for reversed sort order.) 191 | */ 192 | @Test 193 | public void l_harderStream08() { 194 | 195 | List output = 196 | reader.lines() 197 | .map(String::toLowerCase) 198 | .flatMap(SPLIT_PATTERN::splitAsStream) 199 | .filter(s -> s.length() >= 8) 200 | .distinct() 201 | .sorted(Comparator.naturalOrder().reversed()) 202 | .collect(Collectors.toList()); 203 | 204 | assertThat(output).isEqualTo( 205 | Arrays.asList( 206 | "substantial", "ornament", "niggarding", "increase", 207 | "creatures", "contracted", "beauty's", "abundance")); 208 | } 209 | 210 | /** 211 | * Read words from the text file, and sort unique, lower-cased words by length, 212 | * then alphabetically within length, and place the result into an output list. 213 | *

214 | * Remember to use the BufferedReader named "reader" that has already been 215 | * opened for you. 216 | */ 217 | @Test 218 | public void l_harderStream09() { 219 | 220 | List output = 221 | reader.lines() 222 | .map(String::toLowerCase) 223 | .flatMap(SPLIT_PATTERN::splitAsStream) 224 | .distinct() 225 | .sorted(Comparator.comparing(String::length).thenComparing(naturalOrder())) 226 | .collect(Collectors.toList()); 227 | 228 | assertThat(output).isEqualTo( 229 | Arrays.asList( 230 | "a", "as", "be", "by", "in", "or", "to", "we", 231 | "and", "art", "bud", "but", "die", "due", "eat", "foe", 232 | "his", "now", "own", "the", "thy", "too", "bear", "else", 233 | "eyes", "from", "fuel", "heir", "lies", "only", 234 | "pity", "rose", "self", "that", "thee", "this", "thou", 235 | "time", "with", "churl", "cruel", "flame", "fresh", "gaudy", 236 | "grave", "might", "never", "riper", "sweet", "thine", 237 | "waste", "where", "world", "bright", "desire", "famine", 238 | "herald", "mak'st", "making", "memory", "should", "spring", 239 | "tender", "within", "buriest", "content", "decease", 240 | "fairest", "feed'st", "glutton", "light's", "thereby", "world's", "beauty's", 241 | "increase", "ornament", "abundance", "creatures", "contracted", "niggarding", 242 | "substantial")); 243 | } 244 | 245 | 246 | // ======================================================== 247 | // END OF EXERCISES 248 | // TEST INFRASTRUCTURE IS BELOW 249 | // ======================================================== 250 | 251 | // Pattern for splitting a string into words 252 | static final Pattern SPLIT_PATTERN = Pattern.compile("[- .:,]+"); 253 | 254 | private BufferedReader reader; 255 | 256 | @Before 257 | public void z_setUpBufferedReader() throws IOException { 258 | reader = Files.newBufferedReader( 259 | Paths.get("files/Sonnet.txt"), StandardCharsets.UTF_8); 260 | } 261 | 262 | @After 263 | public void z_closeBufferedReader() throws IOException { 264 | reader.close(); 265 | } 266 | } 267 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/D_Streams/M_Reductions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.D_Streams; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import java.io.BufferedReader; 24 | import java.io.IOException; 25 | import java.math.BigInteger; 26 | import java.nio.charset.StandardCharsets; 27 | import java.nio.file.Files; 28 | import java.nio.file.Paths; 29 | import java.util.List; 30 | import java.util.function.Consumer; 31 | import java.util.function.Predicate; 32 | import java.util.regex.Pattern; 33 | import java.util.stream.Collectors; 34 | import java.util.stream.IntStream; 35 | 36 | import static org.assertj.core.api.Assertions.assertThat; 37 | 38 | /** 39 | * This set of exercises covers the reduction step. 40 | *

41 | * Some of these exercises use a BufferedReader variable 42 | * named "reader" that the test has set up for you. 43 | */ 44 | public class M_Reductions { 45 | 46 | /** 47 | * Compute the sums of the 10 first integers starting with 1. 48 | */ 49 | @Test 50 | public void m_reduction01() { 51 | 52 | int sum = IntStream.range(1, 11).sum(); 53 | 54 | assertThat(sum).isEqualTo(55); 55 | } 56 | 57 | /** 58 | * Compute the factorial of 21. This number is quite large. 59 | */ 60 | @Test 61 | public void m_reduction02() { 62 | 63 | BigInteger result = 64 | IntStream.range(1, 22) 65 | .mapToObj(String::valueOf) 66 | .map(BigInteger::new) 67 | .reduce(BigInteger.ONE, BigInteger::multiply); 68 | 69 | assertThat(result).isEqualTo(new BigInteger("51090942171709440000")); 70 | } 71 | 72 | /** 73 | * Given a a list of Consumer, create a single consumer that will pass the 74 | * element it consumes to all the elements of the list. 75 | * Try to use a method reference in your solution. 76 | * The given list contains 10 consumers of StringBuilder. Each of this consumer 77 | * just adds 1..9 to the content of the StringBuilder. 78 | */ 79 | @Test 80 | public void m_reduction03() { 81 | 82 | List> consumers = 83 | IntStream.range(1, 10) 84 | .mapToObj(index -> (Consumer) (sb -> sb.append(index))) 85 | .collect(Collectors.toList()); 86 | 87 | Consumer consumer = 88 | consumers.stream().reduce(sb -> { 89 | }, Consumer::andThen); 90 | 91 | 92 | StringBuilder sb = new StringBuilder("Hello"); 93 | consumer.accept(sb); 94 | 95 | assertThat(sb.toString()).isEqualTo("Hello123456789"); 96 | } 97 | 98 | /** 99 | * Given a a list of Predicates, create a single predicate that will be true if one predicate of the list 100 | * is true. 101 | * Try to use a method reference in your solution. 102 | * The given list contains 10 predicates, each of them tests if the index 1..9 is contained in the 103 | * tested String. 104 | */ 105 | @Test 106 | public void m_reduction04() { 107 | 108 | List> predicates = 109 | IntStream.range(1, 10) 110 | .mapToObj(String::valueOf) 111 | .map(index -> (Predicate) (s -> s.contains(index))) 112 | .collect(Collectors.toList()); 113 | 114 | Predicate predicate = predicates.stream().reduce(s -> false, Predicate::or); 115 | 116 | assertThat(predicate.test("Hello 01")).isTrue(); 117 | assertThat(predicate.test("Hello")).isFalse(); 118 | } 119 | 120 | /** 121 | * Get the last word in the text file. 122 | *

123 | * Remember to use the BufferedReader named "reader" that has already been 124 | * opened for you. 125 | */ 126 | @Test 127 | public void m_reduction05() { 128 | 129 | String result = 130 | reader.lines() 131 | .flatMap(SPLIT_PATTERN::splitAsStream) 132 | .reduce("", (s1, s2) -> s2); 133 | 134 | assertThat(result).isEqualTo("thee"); 135 | } 136 | 137 | 138 | // ======================================================== 139 | // END OF EXERCISES 140 | // TEST INFRASTRUCTURE IS BELOW 141 | // ======================================================== 142 | 143 | // Pattern for splitting a string into words 144 | static final Pattern SPLIT_PATTERN = Pattern.compile("[- .:,]+"); 145 | 146 | private BufferedReader reader; 147 | 148 | @Before 149 | public void z_setUpBufferedReader() throws IOException { 150 | reader = Files.newBufferedReader( 151 | Paths.get("files/Sonnet.txt"), StandardCharsets.UTF_8); 152 | } 153 | 154 | @After 155 | public void z_closeBufferedReader() throws IOException { 156 | reader.close(); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/E_Collectors/O_SimpleCollectors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.E_Collectors; 18 | 19 | import org.junit.Test; 20 | 21 | import java.util.Arrays; 22 | import java.util.Comparator; 23 | import java.util.List; 24 | import java.util.stream.Collectors; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * This set of exercises covers the collect() terminal operation with the basic collectors. 30 | * The collectors used in this class can be built from the factory methods of the Collectors 31 | * factory class. This collectors are the simplest ones: they do not take another, so-called 32 | * downstream collector as a parameter. 33 | */ 34 | public class O_SimpleCollectors { 35 | 36 | /** 37 | * Count the number of elements on that list. 38 | * Try to use a collector from the Collectors factory class. 39 | */ 40 | @Test 41 | public void n_simpleCollector01() { 42 | 43 | List input = Arrays.asList( 44 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 45 | 46 | long count = input.stream().collect(Collectors.counting()); 47 | 48 | assertThat(count).isEqualTo(10L); 49 | } 50 | 51 | /** 52 | * Compute the max element of that list, in the alphabetical order. 53 | * Try to use a collector from the Collectors factory class. 54 | */ 55 | @Test 56 | public void n_simpleCollector02() { 57 | 58 | List input = Arrays.asList( 59 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 60 | 61 | String max = input.stream().collect(Collectors.maxBy(Comparator.naturalOrder())).get(); 62 | 63 | assertThat(max).isEqualTo("two"); 64 | } 65 | 66 | /** 67 | * Compute the min length of the elements of that list. 68 | * Try to use a collector from the Collectors factory class. 69 | */ 70 | @Test 71 | public void n_simpleCollector03() { 72 | 73 | List input = Arrays.asList( 74 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 75 | 76 | int minLength = input.stream().map(String::length).collect(Collectors.minBy(Comparator.naturalOrder())).get(); 77 | 78 | // You can also write it in that way with a single collector: 79 | minLength = input.stream().collect( 80 | Collectors.mapping(String::length, Collectors.minBy(Comparator.naturalOrder()))).get(); 81 | 82 | assertThat(minLength).isEqualTo(3); 83 | } 84 | 85 | /** 86 | * Compute the average length of the elements of that list. 87 | * Try to use a collector from the Collectors factory class. 88 | */ 89 | @Test 90 | public void n_simpleCollector04() { 91 | 92 | List input = Arrays.asList( 93 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 94 | 95 | double averageLength = input.stream().collect(Collectors.averagingDouble(String::length)); 96 | 97 | assertThat(averageLength).isEqualTo(3.9d); 98 | } 99 | 100 | /** 101 | * Compute the sum of the elements of that list. 102 | * Try to use a collector from the Collectors factory class. 103 | */ 104 | @Test 105 | public void n_simpleCollector05() { 106 | 107 | List input = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); 108 | 109 | int sum = input.stream().collect(Collectors.summingInt(number -> number)); 110 | 111 | assertThat(sum).isEqualTo(45); 112 | } 113 | 114 | /** 115 | * Concatenate the elements of that list in a String, separated by a space. 116 | * Try to use a collector from the Collectors factory class. 117 | */ 118 | @Test 119 | public void n_simpleCollector06() { 120 | 121 | List input = Arrays.asList( 122 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 123 | 124 | String result = input.stream().collect(Collectors.joining(" ")); 125 | 126 | assertThat(result).isEqualTo("one two three four five six seven eight nine ten"); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/solutions/java/org/paumard/solutions/codeone2019/E_Collectors/P_HarderCollectors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.solutions.codeone2019.E_Collectors; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Test; 22 | 23 | import java.io.BufferedReader; 24 | import java.io.IOException; 25 | import java.nio.charset.StandardCharsets; 26 | import java.nio.file.Files; 27 | import java.nio.file.Paths; 28 | import java.util.List; 29 | import java.util.Map; 30 | import java.util.Random; 31 | import java.util.function.Function; 32 | import java.util.regex.Pattern; 33 | import java.util.stream.Collectors; 34 | import java.util.stream.IntStream; 35 | import java.util.stream.Stream; 36 | 37 | import static org.assertj.core.api.Assertions.assertThat; 38 | import static org.junit.Assert.assertEquals; 39 | 40 | /** 41 | * This set of exercises covers the collect() terminal operation with the complex collectors. 42 | *

43 | * Some of these exercises use a BufferedReader variable 44 | * named "reader" that the test has set up for you. 45 | */ 46 | public class P_HarderCollectors { 47 | 48 | 49 | /** 50 | * Categorize the words from the text file into a map, where the map's key 51 | * is the length of each word, and the value corresponding to a key is a 52 | * list of words of that length. Don't bother with uniqueness or lower- 53 | * casing the words. 54 | *

55 | * As before, use the BufferedReader variable named 56 | * "reader" that has been set up for you to read from the text file, and 57 | * use SPLIT_PATTERN for splitting the line into words. 58 | */ 59 | @Test 60 | public void o_harderCollector01() { 61 | 62 | Map> result = 63 | reader.lines() 64 | .flatMap(SPLIT_PATTERN::splitAsStream) 65 | .collect( 66 | Collectors.groupingBy(String::length) 67 | ); 68 | 69 | assertThat(result).hasSize(11); 70 | assertThat(result.get(8)).containsExactly("increase", "beauty's", "ornament"); 71 | assertThat(result.get(9)).containsExactly("creatures", "abundance"); 72 | assertThat(result.get(10)).containsExactly("contracted", "niggarding"); 73 | assertThat(result.get(11)).containsExactly("substantial"); 74 | } 75 | 76 | 77 | /** 78 | * Categorize the words from the text file into a map, where the map's key 79 | * is the length of each word, and the value corresponding to a key is a 80 | * count of words of that length. Don't bother with uniqueness or lower- 81 | * casing the words. 82 | *

83 | * This is the same as the previous exercise except 84 | * the map values are the count of words instead of a list of words. 85 | */ 86 | @Test 87 | public void o_harderCollector02() { 88 | 89 | Map result = 90 | reader.lines() 91 | .flatMap(SPLIT_PATTERN::splitAsStream) 92 | .collect( 93 | Collectors.groupingBy(String::length, Collectors.counting()) 94 | ); 95 | 96 | assertThat(result).hasSize(11); 97 | assertThat(result.get(1)).isEqualTo(1L); 98 | assertThat(result.get(2)).isEqualTo(11L); 99 | assertThat(result.get(3)).isEqualTo(28L); 100 | assertThat(result.get(4)).isEqualTo(21L); 101 | assertThat(result.get(5)).isEqualTo(16L); 102 | assertThat(result.get(6)).isEqualTo(12L); 103 | assertThat(result.get(7)).isEqualTo(10L); 104 | assertThat(result.get(8)).isEqualTo(3L); 105 | assertThat(result.get(9)).isEqualTo(2L); 106 | assertThat(result.get(10)).isEqualTo(2L); 107 | assertThat(result.get(11)).isEqualTo(1L); 108 | } 109 | 110 | 111 | /** 112 | * Gather the words from the text file into a map, accumulating a count of 113 | * the number of occurrences of each word. Don't worry about upper case and 114 | * lower case. 115 | *

116 | * Extra challenge: implement two solutions, one that uses 117 | * groupingBy() and the other that uses toMap(). 118 | */ 119 | @Test 120 | public void o_harderCollector03() { 121 | 122 | // with groupingBy() 123 | Map result = 124 | reader.lines() 125 | .flatMap(SPLIT_PATTERN::splitAsStream) 126 | .collect(Collectors.groupingBy( 127 | Function.identity(), Collectors.counting() 128 | )); 129 | 130 | // with toMap() 131 | // result = 132 | // reader.lines() 133 | // .flatMap(SPLIT_PATTERN::splitAsStream) 134 | // .collect(Collectors.toMap( 135 | // Function.identity(), word -> 1L, (l1, l2) -> l1 + l2 136 | // )); 137 | 138 | assertThat(result).hasSize(87); 139 | assertThat(result.get("tender")).isEqualTo(2L); 140 | assertThat(result.get("the")).isEqualTo(6L); 141 | assertThat(result.get("churl")).isEqualTo(1L); 142 | assertThat(result.get("thine")).isEqualTo(2L); 143 | assertThat(result.get("world")).isEqualTo(1L); 144 | assertThat(result.get("thy")).isEqualTo(4L); 145 | assertThat(result.get("self")).isEqualTo(3L); 146 | } 147 | 148 | /** 149 | * Gather all the letters used to write the Sonnet in lower case, and find one of the least used. 150 | *

151 | * Remember to use the BufferedReader named "reader" that has already been 152 | * opened for you. 153 | *

154 | * You can use a variant of the function created for K_SimpleStreams.simpleStream10(). 155 | */ 156 | @Test 157 | public void o_harderCollector04() { 158 | 159 | Function> wordToLetters = 160 | word -> word.chars().filter(Character::isLetter).mapToObj(Character::toString); 161 | 162 | String leastUsedLetter = 163 | reader.lines() 164 | .map(String::toLowerCase) 165 | .flatMap(SPLIT_PATTERN::splitAsStream) 166 | .flatMap(wordToLetters) 167 | .collect(Collectors.groupingBy( 168 | Function.identity(), Collectors.counting() 169 | )) 170 | .entrySet().stream() 171 | .min(Map.Entry.comparingByValue()) 172 | .get() 173 | .getKey(); 174 | 175 | assertThat(leastUsedLetter).isIn("v", "k"); 176 | } 177 | 178 | /** 179 | * Gather all the letters used to write the Sonnet in lower case, and find all the least used in a list. 180 | *

181 | * Remember to use the BufferedReader named "reader" that has already been 182 | * opened for you. 183 | *

184 | * You can use a variant of the function created for K_SimpleStreams.simpleStream10(). 185 | */ 186 | @Test 187 | public void o_harderCollector05() { 188 | 189 | Function> wordToLetters = 190 | word -> word.chars().filter(Character::isLetter).mapToObj(Character::toString); 191 | 192 | 193 | List leastUsedLetters = 194 | reader.lines() 195 | .map(String::toLowerCase) 196 | .flatMap(SPLIT_PATTERN::splitAsStream) 197 | .flatMap(wordToLetters) 198 | .collect(Collectors.groupingBy( 199 | Function.identity(), Collectors.counting() 200 | )) 201 | .entrySet().stream() 202 | .collect(Collectors.groupingBy( 203 | Map.Entry::getValue, 204 | Collectors.mapping(Map.Entry::getKey, Collectors.toList()) 205 | )) 206 | .entrySet().stream() 207 | .min(Map.Entry.comparingByKey()) 208 | .get() 209 | .getValue(); 210 | 211 | assertThat(leastUsedLetters).hasSize(2); 212 | assertThat(leastUsedLetters).contains("v", "k"); 213 | } 214 | 215 | 216 | /** 217 | * From the words in the text file, create nested maps, where the outer map is a 218 | * map from the first letter of the word to an inner map. (Use a string of length 219 | * one as the key.) The inner map, in turn, is a mapping from the length of the 220 | * word to a list of words with that length. Don't bother with any lowercasing 221 | * or uniquifying of the words. 222 | *

223 | * For example, given the words "foo bar baz bazz foo" the string 224 | * representation of the result would be: 225 | * {b={3=[bar, baz], 4=[bazz]}, f={3=[foo, foo]}} 226 | */ 227 | @Test 228 | public void o_harderCollector06() { 229 | 230 | Map>> result = 231 | reader.lines() 232 | .flatMap(SPLIT_PATTERN::splitAsStream) 233 | .collect(Collectors.groupingBy( 234 | word -> word.substring(0, 1), 235 | Collectors.groupingBy(String::length))); 236 | 237 | assertThat(result).hasSize(25); 238 | assertThat(result.get("a").get(9).toString()).isEqualTo("[abundance]"); 239 | assertThat(result.get("b").get(2).toString()).isEqualTo("[by, be, by]"); 240 | assertThat(result.get("f").get(5).toString()).isEqualTo("[flame, fresh]"); 241 | assertThat(result.get("g").get(5).toString()).isEqualTo("[gaudy, grave]"); 242 | assertThat(result.get("s").get(6).toString()).isEqualTo("[should, spring]"); 243 | assertThat(result.get("s").get(11).toString()).isEqualTo("[substantial]"); 244 | assertThat(result.get("t").get(3).toString()).isEqualTo("[the, thy, thy, thy, too, the, the, thy, the, the, the]"); 245 | assertThat(result.get("w").get(5).toString()).isEqualTo("[where, waste, world]"); 246 | } 247 | 248 | 249 | /** 250 | * Given a stream of integers, compute separate sums of the even and odd values 251 | * in this stream. Since the input is a stream, this necessitates making a single 252 | * pass over the input. 253 | */ 254 | @Test 255 | public void o_harderCollector07() { 256 | 257 | IntStream input = new Random(987523).ints(20, 0, 100); 258 | 259 | Map result = 260 | input.boxed() 261 | .collect(Collectors.partitioningBy( 262 | number -> number % 2 == 0, Collectors.summingInt(number -> number) 263 | )); 264 | 265 | int sumEvens = result.get(true); 266 | int sumOdds = result.get(false); 267 | 268 | assertEquals(516, sumEvens); 269 | assertEquals(614, sumOdds); 270 | } 271 | 272 | 273 | // ======================================================== 274 | // END OF EXERCISES 275 | // TEST INFRASTRUCTURE IS BELOW 276 | // ======================================================== 277 | 278 | 279 | // Pattern for splitting a string into words 280 | static final Pattern SPLIT_PATTERN = Pattern.compile("[- .:,]+"); 281 | 282 | private BufferedReader reader; 283 | 284 | @Before 285 | public void z_setUpBufferedReader() throws IOException { 286 | reader = Files.newBufferedReader( 287 | Paths.get("files/Sonnet.txt"), StandardCharsets.UTF_8); 288 | } 289 | 290 | @After 291 | public void z_closeBufferedReader() throws IOException { 292 | reader.close(); 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/A_Lambdas/a_lambdas/A_Suppliers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | import org.paumard.codeone2019.A_Lambdas.a_lambdas.model.Circle; 22 | import org.paumard.codeone2019.A_Lambdas.a_lambdas.util.CircleFactory; 23 | 24 | import java.util.List; 25 | import java.util.function.Supplier; 26 | 27 | import static org.assertj.core.api.Assertions.assertThat; 28 | 29 | /** 30 | * This set of exercises covers the Supplier interface. 31 | */ 32 | public class A_Suppliers { 33 | 34 | /** 35 | * Write a lambda expression that returns a new StringBuilder 36 | * containing the string "abc". 37 | */ 38 | @Test 39 | @Ignore 40 | public void a_supplier01() { 41 | 42 | Supplier sup = null; // TODO 43 | 44 | assertThat(sup.get().toString()).isEqualTo("abc"); 45 | } 46 | 47 | /** 48 | * Write a lambda expression that returns a new, empty StringBuilder. 49 | * Try to write it using a method reference. 50 | */ 51 | @Test 52 | @Ignore 53 | public void a_supplier02() { 54 | 55 | Supplier sup = null; // TODO 56 | 57 | assertThat(sup.get().toString()).isEqualTo(""); 58 | } 59 | 60 | /** 61 | * Write a lambda expression that returns a new Circle. 62 | * The Circle class is provided in the model package. 63 | */ 64 | @Test 65 | @Ignore 66 | public void a_supplier03() { 67 | 68 | Supplier sup = null; // TODO 69 | 70 | assertThat(sup.get().toString()).isEqualTo("Circle{color=White}"); 71 | } 72 | 73 | /** 74 | * Use the provided CircleFactory interface, that extends Supplier<Circle>. 75 | * Add a method to this interface that can create a list of three circles. 76 | */ 77 | @Test 78 | @Ignore 79 | public void a_supplier04() { 80 | 81 | CircleFactory circleFactory = null; // TODO 82 | 83 | List circles = circleFactory.getThree(); 84 | 85 | assertThat(circles).containsExactly(new Circle(), new Circle(), new Circle()); 86 | } 87 | 88 | /** 89 | * Use the provided CircleFactory interface, that extends Supplier<Circle>. 90 | * Add a method to this interface that can create a list of three red circles. 91 | */ 92 | @Test 93 | @Ignore 94 | public void a_supplier05() { 95 | 96 | CircleFactory circleFactory = null; // TODO 97 | 98 | List circles = circleFactory.getThree(); 99 | 100 | assertThat(circles).containsExactly(new Circle("Red"), new Circle("Red"), new Circle("Red")); 101 | } 102 | 103 | /** 104 | * Writing our factory in that way is not very nice. We would like to create a factor method 105 | * to create a CircleFactory, and be able to call in that way: 106 | *

107 | * CircleFactory factory = CircleFactory.createFactory(Circle::new); 108 | * In that case, the factory should be a factory of white circles. 109 | */ 110 | @Test 111 | @Ignore 112 | public void a_supplier06() { 113 | 114 | // The method call has been commented so that the code still compiles. 115 | // Once you have created it, you should uncomment the call on the following line 116 | CircleFactory circleFactory = null; // CircleFactory.createFactory(Circle::new); 117 | 118 | List circles = circleFactory.getThree(); 119 | 120 | assertThat(circles).containsExactly(new Circle("White"), new Circle("White"), new Circle("White")); 121 | } 122 | 123 | /** 124 | * And what about creating a factory of colored Circle in that way: 125 | *

126 | * CircleFactory factory = CircleFactory.createFactory(Circle::new, "Blue"); 127 | * It needs another createFactory() method with two arguments. 128 | */ 129 | @Test 130 | @Ignore 131 | public void a_supplier07() { 132 | 133 | // The method call has been commented so that the code still compiles. 134 | // Once you have created it, you should uncomment the call on the following line 135 | CircleFactory circleFactory = null; // CircleFactory.createFactory(Circle::new, "Blue"); 136 | 137 | List circles = circleFactory.getThree(); 138 | 139 | assertThat(circles).containsExactly(new Circle("Blue"), new Circle("Blue"), new Circle("Blue")); 140 | } 141 | } 142 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/A_Lambdas/a_lambdas/B_Consumers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | 22 | import java.util.*; 23 | import java.util.function.BiConsumer; 24 | import java.util.function.Consumer; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | import static org.junit.Assert.assertTrue; 28 | 29 | /** 30 | * This set of exercises covers the Consumer and BiConsumer interfaces. 31 | * Some exercises also cover consumer chaining. 32 | */ 33 | public class B_Consumers { 34 | 35 | /** 36 | * Write a lambda expression that clears the given list. 37 | * Try to write this lambda using a method reference. 38 | */ 39 | @Test 40 | @Ignore 41 | public void b_consumer01() { 42 | 43 | Consumer> cons = null; // TODO 44 | 45 | List list = new ArrayList<>(Arrays.asList("a", "b", "c")); 46 | cons.accept(list); 47 | assertTrue(list.isEmpty()); 48 | } 49 | 50 | /** 51 | * Write a lambda expression that appends the 52 | * string ")" to the given StringBuilder. 53 | */ 54 | @Test 55 | @Ignore 56 | public void b_consumer02() { 57 | 58 | Consumer cons = null; // TODO 59 | 60 | StringBuilder sb = new StringBuilder("Hello"); 61 | cons.accept(sb); 62 | assertThat(sb.toString()).isEqualTo("Hello)"); 63 | } 64 | 65 | /** 66 | * Write a lambda expression that adds the 67 | * string "(" as the first element of the given StringBuilder. 68 | */ 69 | @Test 70 | @Ignore 71 | public void b_consumer03() { 72 | 73 | Consumer cons = null; // TODO 74 | 75 | StringBuilder sb = new StringBuilder("Hello"); 76 | cons.accept(sb); 77 | assertThat(sb.toString()).isEqualTo("(Hello"); 78 | } 79 | 80 | /** 81 | * Write a lambda expression that adds the 82 | * string "(" as the first element of the given StringBuilder 83 | * and the string ")" as the last element of the given StringBuilder. 84 | * Try to use the consumers written for b_consumer2() 85 | * and b_consumer3() 86 | */ 87 | @Test 88 | @Ignore 89 | public void b_consumer04() { 90 | 91 | Consumer cons = null; // TODO 92 | 93 | StringBuilder sb = new StringBuilder("Hello"); 94 | cons.accept(sb); 95 | assertThat(sb.toString()).isEqualTo("(Hello)"); 96 | } 97 | 98 | /** 99 | * Write a lambda expression that adds the given string to the 100 | * given list. Try to write this lambda as a method reference. 101 | */ 102 | @Test 103 | @Ignore 104 | public void b_consumer05() { 105 | 106 | List strings = new ArrayList<>(Arrays.asList("one", "two", "three")); 107 | 108 | BiConsumer, String> bicons = null; // TODO 109 | bicons.accept(strings, "four"); 110 | 111 | assertThat(strings).containsExactly("one", "two", "three", "four"); 112 | } 113 | 114 | /** 115 | * Write a lambda expression that adds the given key and value to the 116 | * map. Try to write this lambda as a method reference. 117 | */ 118 | @Test 119 | @Ignore 120 | public void b_consumer06() { 121 | 122 | Map map = new HashMap<>(); 123 | map.put(1, "one"); 124 | map.put(2, "two"); 125 | map.put(3, "three"); 126 | 127 | BiConsumer bicons = null; // TODO 128 | bicons.accept(4, "four"); 129 | 130 | assertThat(map).containsKeys(1, 2, 3, 4); 131 | assertThat(map.get(4)).isEqualTo("four"); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/A_Lambdas/a_lambdas/C_Predicates.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | 22 | import java.util.function.Predicate; 23 | 24 | import static org.junit.Assert.assertFalse; 25 | import static org.junit.Assert.assertTrue; 26 | 27 | /** 28 | * This set of exercises covers the Predicate interface. 29 | * Some exercises also cover predicate chaining. 30 | */ 31 | public class C_Predicates { 32 | 33 | /** 34 | * Write a lambda expression that is a predicate 35 | * that tests whether a string null. 36 | * Try to write this lambda using a method reference. 37 | */ 38 | @Test 39 | @Ignore 40 | public void c_predicate01() { 41 | 42 | Predicate pred = (String s) -> s == null; 43 | 44 | assertTrue(pred.test(null)); 45 | assertFalse(pred.test("")); 46 | } 47 | 48 | /** 49 | * Write a lambda expression that is a predicate 50 | * that tests whether a string is empty. 51 | * Try to write this lambda using a method reference. 52 | */ 53 | @Test 54 | @Ignore 55 | public void c_predicate02() { 56 | 57 | Predicate pred = (String s) -> s.isEmpty(); // TODO 58 | 59 | assertTrue(pred.test("")); 60 | assertFalse(pred.test("a")); 61 | } 62 | 63 | /** 64 | * Create a predicate that returns true when the given String 65 | * is non-null. Try to use the predicate you wrote 66 | * for c_predicate01() 67 | */ 68 | @Test 69 | @Ignore 70 | public void c_predicate03() { 71 | 72 | Predicate pred = null; // TODO 73 | 74 | assertTrue(pred.test("")); 75 | assertFalse(pred.test(null)); 76 | } 77 | 78 | /** 79 | * Create a predicate that returns true when the given String 80 | * is null or empty. Try to use the predicates you wrote 81 | * for c_predicate01() c_predicate02() 82 | */ 83 | @Test 84 | @Ignore 85 | public void c_predicate04() { 86 | 87 | Predicate pred = null; // TODO 88 | 89 | assertTrue(pred.test("")); 90 | assertTrue(pred.test(null)); 91 | assertFalse(pred.test("Hello")); 92 | } 93 | 94 | /** 95 | * Create a predicate that returns true when the given String 96 | * is non-null and non-empty. You can use the predicates you 97 | * wrote for c_predicate01() c_predicate02() or the one 98 | * you wrote for c_predicate04() 99 | */ 100 | @Test 101 | @Ignore 102 | public void c_predicate05() { 103 | 104 | Predicate pred = null; // TODO 105 | 106 | assertFalse(pred.test("")); 107 | assertFalse(pred.test(null)); 108 | assertTrue(pred.test("Hello")); 109 | } 110 | 111 | /** 112 | * Write a lambda expression that is a predicate 113 | * that tests whether a string is shorter than four characters. 114 | */ 115 | @Test 116 | @Ignore 117 | public void c_predicate06() { 118 | 119 | Predicate pred = null; // TODO 120 | 121 | assertTrue(pred.test("abc")); 122 | assertFalse(pred.test("abcd")); 123 | assertFalse(pred.test("abcde")); 124 | } 125 | 126 | /** 127 | * Create a predicate that is true if the provided string equals ERROR. 128 | * Try writing it using a method reference. 129 | */ 130 | @Test 131 | @Ignore 132 | public void c_predicate07() { 133 | 134 | Predicate equalsError = null; // TODO 135 | 136 | assertFalse(equalsError.test("Hello")); 137 | assertTrue(equalsError.test("ERROR")); 138 | assertFalse(equalsError.test(null)); 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/A_Lambdas/a_lambdas/D_Functions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | 22 | import java.util.function.BiFunction; 23 | import java.util.function.Function; 24 | 25 | import static org.assertj.core.api.Assertions.assertThat; 26 | 27 | /** 28 | * This set of exercises covers the Function interface. 29 | * Some exercises also cover function chaining and composition. 30 | */ 31 | public class D_Functions { 32 | 33 | /** 34 | * Write a lambda expression that converts the 35 | * given string to upper case. Try to write this lambda 36 | * as a method reference. 37 | */ 38 | @Test 39 | @Ignore 40 | public void d_function01() { 41 | 42 | Function func = null; // TODO 43 | 44 | assertThat(func.apply("abc")).isEqualTo("ABC"); 45 | } 46 | 47 | /** 48 | * Write a lambda expression that wraps the given 49 | * string in parentheses. 50 | */ 51 | @Test 52 | @Ignore 53 | public void d_function02() { 54 | 55 | Function func = null; // TODO 56 | 57 | assertThat(func.apply("abc")).isEqualTo("(abc)"); 58 | } 59 | 60 | /** 61 | * Write a lambda expression that returns the length of the 62 | * given String. Try to write this lambda as a method reference. 63 | */ 64 | @Test 65 | @Ignore 66 | public void d_function03() { 67 | 68 | Function func = null; // TODO 69 | 70 | assertThat(func.apply("")).isEqualTo(0); 71 | assertThat(func.apply("Hello!")).isEqualTo(6); 72 | } 73 | 74 | /** 75 | * Write a lambda expression that returns an empty String 76 | * if the given string is null, and the given string otherwise. 77 | */ 78 | @Test 79 | @Ignore 80 | public void d_function04() { 81 | 82 | Function func = null; // TODO 83 | 84 | assertThat(func.apply(null)).isEqualTo(""); 85 | assertThat(func.apply("")).isEqualTo(""); 86 | assertThat(func.apply("Hello")).isEqualTo("Hello"); 87 | } 88 | 89 | /** 90 | * Write a lambda expression that returns the length of the given 91 | * String if it is not null, and 0 if the given String is null. 92 | * Try using the a_lambdas written in d_function3() and d_function4() 93 | */ 94 | @Test 95 | @Ignore 96 | public void d_function05() { 97 | 98 | Function func = null; // TODO 99 | 100 | assertThat(func.apply(null)).isEqualTo(0); 101 | assertThat(func.apply("")).isEqualTo(0); 102 | assertThat(func.apply("Hello")).isEqualTo(5); 103 | } 104 | 105 | /** 106 | * Write a lambda expression that, given two strings, returns the result 107 | * of concatenating the first with the second, followed by the 108 | * first again. 109 | */ 110 | @Test 111 | @Ignore 112 | public void d_function06() { 113 | 114 | BiFunction bifunc = null; // TODO 115 | 116 | assertThat(bifunc.apply("-", "Hello")).isEqualTo("-Hello-"); 117 | } 118 | 119 | /** 120 | * Write a lambda expression that returns the index of 121 | * the first occurrence of the second string within the first string, 122 | * or -1 if the second string doesn't occur within the first string. 123 | * Try to write this lambda using a method reference. 124 | */ 125 | @Test 126 | @Ignore 127 | public void d_function07() { 128 | 129 | BiFunction bifunc = null; // TODO 130 | 131 | assertThat(bifunc.apply("Hello world", "Hello")).isEqualTo(0); 132 | assertThat(bifunc.apply("Hello world", "world")).isEqualTo(6); 133 | } 134 | 135 | /** 136 | * Write a lambda expression that returns the index of 137 | * the first occurrence of the given string within the string 138 | * "Hello world", or -1 if the given string is not found. 139 | * Try to write this lambda using a method reference. 140 | */ 141 | @Test 142 | @Ignore 143 | public void d_function08() { 144 | 145 | String pattern = "Hello world!"; 146 | Function func = null; // TODO 147 | 148 | assertThat(func.apply("Hello")).isEqualTo(0); 149 | assertThat(func.apply("world")).isEqualTo(6); 150 | } 151 | 152 | /** 153 | * Write a lambda expression that returns the index of 154 | * the first occurrence of the given string within the string 155 | * "Hello world", or -1 if the given string is not found. 156 | * Try to write this lambda as a partial application of the 157 | * lambda you wrote in d_function07(). 158 | */ 159 | @Test 160 | @Ignore 161 | public void d_function09() { 162 | 163 | String pattern = "Hello world!"; 164 | 165 | Function func = null; // TODO 166 | 167 | assertThat(func.apply("Hello")).isEqualTo(0); 168 | assertThat(func.apply("world")).isEqualTo(6); 169 | } 170 | 171 | } 172 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/A_Lambdas/a_lambdas/E_Runnables.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.A_Lambdas.a_lambdas; 18 | 19 | import org.assertj.core.api.Assertions; 20 | import org.junit.Ignore; 21 | import org.junit.Test; 22 | 23 | /** 24 | * This set of exercises covers the Runnable interface. 25 | */ 26 | public class E_Runnables { 27 | 28 | /** 29 | * Write a lambda expression that appends the string suffix 30 | * to the sb variable (a StringBuilder). 31 | */ 32 | @Test 33 | @Ignore 34 | public void e_runnable01() { 35 | 36 | StringBuilder sb = new StringBuilder("abc"); 37 | String suffix = "--"; 38 | 39 | Runnable r = null; // TODO 40 | 41 | r.run(); 42 | r.run(); 43 | r.run(); 44 | Assertions.assertThat(sb.toString()).isEqualTo("abc------"); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/A_Lambdas/a_lambdas/model/Circle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.A_Lambdas.a_lambdas.model; 18 | 19 | import java.util.Objects; 20 | 21 | public class Circle { 22 | 23 | private String color; 24 | 25 | public Circle() { 26 | this("White"); 27 | } 28 | 29 | public Circle(String color) { 30 | this.color = color; 31 | } 32 | 33 | public String getColor() { 34 | return color; 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "Circle{color=" + color + "}"; 40 | } 41 | 42 | @Override 43 | public boolean equals(Object o) { 44 | if (this == o) return true; 45 | if (o == null || getClass() != o.getClass()) return false; 46 | Circle circle = (Circle) o; 47 | return color.equals(circle.color); 48 | } 49 | 50 | @Override 51 | public int hashCode() { 52 | return Objects.hash(color); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/A_Lambdas/a_lambdas/util/CircleFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.A_Lambdas.a_lambdas.util; 18 | 19 | import org.paumard.codeone2019.A_Lambdas.a_lambdas.model.Circle; 20 | 21 | import java.util.List; 22 | import java.util.function.Supplier; 23 | 24 | public interface CircleFactory extends Supplier { 25 | 26 | default List getThree() { 27 | return null; // TODO 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/A_Lambdas/b_comparators/F_Comparators.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.A_Lambdas.b_comparators; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | import org.paumard.codeone2019.A_Lambdas.b_comparators.model.Person; 22 | 23 | import java.util.Comparator; 24 | import java.util.function.IntBinaryOperator; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * This set of exercises covers the Comparator interface. 30 | * Comparator chaining and factory methods are also covered. The code you need 31 | * to write uses the factory methods and default methods of the Comparator interface. 32 | */ 33 | public class F_Comparators { 34 | 35 | final Person michael = new Person("Michael", "Jackson", 51); 36 | final Person rod = new Person("Rod", "Stewart", 71); 37 | final Person paul = new Person("Paul", "McCartney", 74); 38 | final Person mick = new Person("Mick", "Jagger", 73); 39 | final Person jermaine = new Person("Jermaine", "Jackson", 61); 40 | 41 | /** 42 | * Write a Comparator that compare instances of String using their length. 43 | * For instance FOUR (4 letters) is greater than TWO (three letters) 44 | */ 45 | @Test 46 | @Ignore 47 | public void f_comparator01() { 48 | 49 | Comparator compareByLength = null; // TODO 50 | 51 | assertThat(compareByLength.compare("FOUR", "TWO")).isGreaterThan(0); 52 | assertThat(compareByLength.compare("ONE", "SEVEN")).isLessThan(0); 53 | assertThat(compareByLength.compare("ONE", "TWO")).isEqualTo(0); 54 | } 55 | 56 | /** 57 | * Write a Comparator that compare instances of String using their length. 58 | * If the lengths are the same, then use the alphabetical order. 59 | */ 60 | @Test 61 | @Ignore 62 | public void f_comparator02() { 63 | 64 | Comparator compareByLengthThenAlphabetical = null; // TODO 65 | 66 | assertThat(compareByLengthThenAlphabetical.compare("FOUR", "TWO")).isGreaterThan(0); 67 | assertThat(compareByLengthThenAlphabetical.compare("ONE", "SEVEN")).isLessThan(0); 68 | assertThat(compareByLengthThenAlphabetical.compare("ONE", "TWO")).isLessThan(0); 69 | assertThat(compareByLengthThenAlphabetical.compare("FOUR", "FIVE")).isGreaterThan(0); 70 | assertThat(compareByLengthThenAlphabetical.compare("EIGHT", "EIGHT")).isEqualTo(0); 71 | } 72 | 73 | /** 74 | * Write a Comparator that compares instances of Person using their lastName. 75 | */ 76 | @Test 77 | @Ignore 78 | public void f_comparator03() { 79 | 80 | Comparator compareByLastName = null; // TODO 81 | 82 | assertThat(compareByLastName.compare(michael, rod)).isLessThan(0); 83 | assertThat(compareByLastName.compare(paul, paul)).isEqualTo(0); 84 | assertThat(compareByLastName.compare(michael, jermaine)).isEqualTo(0); 85 | } 86 | 87 | /** 88 | * Write a Comparator that compares instances of Person using their 89 | * lastName, and if their last name is the same, uses their first name. 90 | */ 91 | @Test 92 | @Ignore 93 | public void f_comparator04() { 94 | 95 | Comparator compareByLastNameThenFirstName = null; // TODO 96 | 97 | assertThat(compareByLastNameThenFirstName.compare(michael, rod)).isLessThan(0); 98 | assertThat(compareByLastNameThenFirstName.compare(paul, paul)).isEqualTo(0); 99 | assertThat(compareByLastNameThenFirstName.compare(michael, jermaine)).isGreaterThan(0); 100 | } 101 | 102 | /** 103 | * Write a Comparator that compares the people in the order reversed from 104 | * the one you wrote in the comparator04() exercise. 105 | */ 106 | @Test 107 | @Ignore 108 | public void f_comparator05() { 109 | 110 | Comparator compareByLastNameThenFirstNameReversed = null; // TODO 111 | 112 | assertThat(compareByLastNameThenFirstNameReversed.compare(michael, rod)).isGreaterThan(0); 113 | assertThat(compareByLastNameThenFirstNameReversed.compare(paul, paul)).isEqualTo(0); 114 | assertThat(compareByLastNameThenFirstNameReversed.compare(michael, jermaine)).isLessThan(0); 115 | } 116 | 117 | /** 118 | * Write a Comparator that compares the people in the same order than the 119 | * one you wrote in comparator04(), but that supports null values. The null 120 | * values should be considered greater than any non-null values. 121 | */ 122 | @Test 123 | @Ignore 124 | public void f_comparator06() { 125 | 126 | Comparator compareByLastNameThenFirstNameWithNull = null; // TODO 127 | 128 | assertThat(compareByLastNameThenFirstNameWithNull.compare(michael, rod)).isLessThan(0); 129 | assertThat(compareByLastNameThenFirstNameWithNull.compare(paul, paul)).isEqualTo(0); 130 | assertThat(compareByLastNameThenFirstNameWithNull.compare(michael, jermaine) > 0); 131 | assertThat(compareByLastNameThenFirstNameWithNull.compare(mick, null)).isLessThan(0); 132 | assertThat(compareByLastNameThenFirstNameWithNull.compare(null, mick)).isGreaterThan(0); 133 | } 134 | 135 | /** 136 | * Write a Comparator that compares two people by age. 137 | * Try to write the comparator so as to avoid boxing of primitives. 138 | */ 139 | @Test 140 | @Ignore 141 | public void f_comparator07() { 142 | 143 | Comparator compareByAge = null; // TODO 144 | 145 | assertThat(compareByAge.compare(michael, rod)).isLessThan(0); 146 | assertThat(compareByAge.compare(paul, paul)).isEqualTo(0); 147 | assertThat(compareByAge.compare(mick, jermaine)).isGreaterThan(0); 148 | } 149 | 150 | /** 151 | * Write a Comparator that compares two people using the fact that the Person 152 | * class implements Comparable. Try to use a factory method from the 153 | * Comparator interface. 154 | */ 155 | @Test 156 | @Ignore 157 | public void f_comparator08() { 158 | 159 | Comparator compare = null; // TODO 160 | 161 | assertThat(compare.compare(michael, rod)).isLessThan(0); 162 | assertThat(compare.compare(paul, paul)).isEqualTo(0); 163 | assertThat(compare.compare(mick, jermaine)).isGreaterThan(0); 164 | assertThat(compare.compare(michael, jermaine)).isGreaterThan(0); 165 | } 166 | 167 | 168 | /** 169 | * Write a lambda expression that compares two int values and returns an 170 | * int result that is less than, equal to, or greater than zero, like 171 | * a comparator. Watch out for overflow. The Comparator interface takes 172 | * two objects, but in this case we are comparing int primitives, so the 173 | * functional interface we use is IntBinaryOperator. 174 | */ 175 | @Test 176 | @Ignore 177 | public void f_comparator09() { 178 | 179 | IntBinaryOperator intCompare = null; // TODO 180 | 181 | assertThat(intCompare.applyAsInt(0, 1)).isLessThan(0); 182 | assertThat(intCompare.applyAsInt(1, 1)).isEqualTo(0); 183 | assertThat(intCompare.applyAsInt(2, 1) > 0); 184 | assertThat(intCompare.applyAsInt(Integer.MIN_VALUE, Integer.MAX_VALUE)).isLessThan(0); 185 | assertThat(intCompare.applyAsInt(Integer.MAX_VALUE, Integer.MIN_VALUE)).isGreaterThan(0); 186 | } 187 | 188 | /** 189 | * Write a method reference that compares two int values and returns an 190 | * int result that is less than, equal to, or greater than zero, like 191 | * a comparator. 192 | */ 193 | @Test 194 | @Ignore 195 | public void f_comparator10() { 196 | 197 | IntBinaryOperator intCompare = null; // TODO 198 | 199 | assertThat(intCompare.applyAsInt(0, 1)).isLessThan(0); 200 | assertThat(intCompare.applyAsInt(1, 1)).isEqualTo(0); 201 | assertThat(intCompare.applyAsInt(2, 1)).isGreaterThan(0); 202 | assertThat(intCompare.applyAsInt(Integer.MIN_VALUE, Integer.MAX_VALUE)).isLessThan(0); 203 | assertThat(intCompare.applyAsInt(Integer.MAX_VALUE, Integer.MIN_VALUE)).isGreaterThan(0); 204 | } 205 | 206 | interface DoubleToIntBiFunction { 207 | int applyAsInt(double a, double b); 208 | } 209 | 210 | /** 211 | * Write a method reference that compares two double values and returns an 212 | * int result that is less than, equal to, or greater than zero, like 213 | * a comparator. There functional interface that takes two doubles and returns 214 | * an int, so we define one here. Comparing double values introduces 215 | * special cases such NaN. Consider all NaN values to be equal to each other 216 | * and greater than any non-NaN value. 217 | */ 218 | @Test 219 | @Ignore 220 | public void f_comparator11() { 221 | 222 | DoubleToIntBiFunction doubleCompare = null; // TODO 223 | 224 | assertThat(doubleCompare.applyAsInt(0.0, 1.0)).isLessThan(0); 225 | assertThat(doubleCompare.applyAsInt(1.0, 1.0)).isEqualTo(0); 226 | assertThat(doubleCompare.applyAsInt(2.0, 1.0)).isGreaterThan(0); 227 | assertThat(doubleCompare.applyAsInt(Double.NaN, Double.NaN)).isEqualTo(0); 228 | assertThat(doubleCompare.applyAsInt(Double.NaN, 0.0)).isGreaterThan(0); 229 | assertThat(doubleCompare.applyAsInt(0.0, Double.NaN)).isLessThan(0); 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/A_Lambdas/b_comparators/model/Person.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.A_Lambdas.b_comparators.model; 18 | 19 | public class Person implements Comparable { 20 | 21 | private String lastName; 22 | private String firstName; 23 | private int age; 24 | 25 | public Person(String firstName, String lastName, int age) { 26 | this.lastName = lastName; 27 | this.firstName = firstName; 28 | this.age = age; 29 | } 30 | 31 | public String getLastName() { 32 | return lastName; 33 | } 34 | 35 | public void setLastName(String lastName) { 36 | this.lastName = lastName; 37 | } 38 | 39 | public String getFirstName() { 40 | return firstName; 41 | } 42 | 43 | public void setFirstName(String firstName) { 44 | this.firstName = firstName; 45 | } 46 | 47 | public int getAge() { 48 | return age; 49 | } 50 | 51 | public void setAge(int age) { 52 | this.age = age; 53 | } 54 | 55 | @Override 56 | public int compareTo(Person other) { 57 | int compareByLastName = lastName.compareTo(other.lastName); 58 | if (compareByLastName == 0) { 59 | int compareByFirstName = firstName.compareTo(other.firstName); 60 | if (compareByFirstName == 0) { 61 | return Integer.compare(age, other.age); 62 | } else { 63 | return compareByFirstName; 64 | } 65 | } else { 66 | return compareByLastName; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/B_Collections/G_Iterables.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.B_Collections; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | 22 | import java.util.Arrays; 23 | import java.util.List; 24 | import java.util.stream.Collectors; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * This set of exercises covers the default method added to the Iterable interface. 30 | */ 31 | public class G_Iterables { 32 | 33 | /** 34 | * Given a list of StringBuilders, modify each StringBuilder 35 | * in-place by appending the string "new" to each one. 36 | */ 37 | @Test 38 | @Ignore 39 | public void g_iterable01() { 40 | 41 | List sbList = Arrays.asList( 42 | new StringBuilder("alfa"), 43 | new StringBuilder("bravo"), 44 | new StringBuilder("charlie")); 45 | 46 | // TODO write code to modify sbList 47 | 48 | List strings = sbList.stream() 49 | .map(StringBuilder::toString) 50 | .collect(Collectors.toList()); 51 | 52 | assertThat(strings).hasSize(3); 53 | assertThat(strings).contains("alfanew", "bravonew", "charlienew"); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/B_Collections/H_Collections.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.B_Collections; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | 22 | import java.util.ArrayList; 23 | import java.util.Arrays; 24 | import java.util.List; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * This set of exercises covers the default method added to the Collection interface. 30 | */ 31 | public class H_Collections { 32 | 33 | /** 34 | * Remove the words that have odd lengths from the list. 35 | */ 36 | @Test 37 | @Ignore 38 | public void h_collection01() { 39 | 40 | List list = new ArrayList<>(Arrays.asList( 41 | "alfa", "bravo", "charlie", "delta", "echo", "foxtrot")); 42 | 43 | // TODO write code to modify list 44 | 45 | assertThat(list).hasSize(2); 46 | assertThat(list).contains("alfa", "echo"); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/B_Collections/I_Lists.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.B_Collections; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | 22 | import java.util.Arrays; 23 | import java.util.List; 24 | 25 | import static org.assertj.core.api.Assertions.assertThat; 26 | 27 | /** 28 | * This set of exercises covers the default method added to the List interface. 29 | */ 30 | public class I_Lists { 31 | 32 | /** 33 | * Replace every word in the list with its upper case equivalent. 34 | */ 35 | @Test 36 | @Ignore 37 | public void i_list01() { 38 | 39 | List strings = Arrays.asList( 40 | "alfa", "bravo", "charlie", "delta", "echo", "foxtrot"); 41 | 42 | // TODO code to modify list 43 | 44 | assertThat(strings).containsExactly("ALFA", "BRAVO", "CHARLIE", "DELTA", "ECHO", "FOXTROT"); 45 | } 46 | 47 | /** 48 | * Replace every null value in the list with an empty String. 49 | */ 50 | @Test 51 | @Ignore 52 | public void i_list02() { 53 | 54 | List strings = Arrays.asList( 55 | "alfa", null, "charlie", "delta", null, "foxtrot"); 56 | 57 | // TODO code to modify strings 58 | 59 | assertThat(strings).containsExactly("alfa", "", "charlie", "delta", "", "foxtrot"); 60 | } 61 | 62 | /** 63 | * Sort the content of the list in the alphabetical order of the strings. 64 | * Try to use a factory method from Comparator. 65 | */ 66 | @Test 67 | @Ignore 68 | public void i_list03() { 69 | 70 | List strings = Arrays.asList( 71 | "one", "two", "three", "four", "five", "six"); 72 | 73 | // TODO code to modify strings 74 | 75 | assertThat(strings).containsExactly("five", "four", "one", "six", "three", "two"); 76 | } 77 | 78 | /** 79 | * Sort the content of the list by the length of the strings. In case the length is the same, 80 | * then use the alphabetical order. 81 | * Try to use a factory method from Comparator. 82 | */ 83 | @Test 84 | @Ignore 85 | public void i_list04() { 86 | 87 | List strings = Arrays.asList( 88 | "one", "two", "three", "four", "five", "six"); 89 | 90 | // TODO code to modify strings 91 | 92 | assertThat(strings).containsExactly("one", "six", "two", "five", "four", "three"); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/D_Streams/K_SimpleStreams.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.D_Streams; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | 22 | import java.util.Arrays; 23 | import java.util.List; 24 | import java.util.function.Function; 25 | 26 | import static org.assertj.core.api.Assertions.assertThat; 27 | 28 | /** 29 | * This set of exercises covers simple simpleStream pipelines, 30 | * including intermediate operations and basic collectors. 31 | */ 32 | public class K_SimpleStreams { 33 | 34 | /** 35 | * Given a list of words, create an output list that contains the elements 36 | * converted to upper case. 37 | * Use the collect(Collectors.toList()) pattern to create the output list. 38 | */ 39 | @Test 40 | @Ignore 41 | public void k_simpleStream01() { 42 | 43 | List input = Arrays.asList( 44 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 45 | 46 | List result = null; // TODO 47 | 48 | assertThat(result) 49 | .containsExactly("ONE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", "EIGHT", "NINE", "TEN"); 50 | } 51 | 52 | /** 53 | * Given a list of words, create an output list that contains 54 | * only the odd-length words, converted to upper case. 55 | * Use the collect(Collectors.toList()) pattern to create the output list. 56 | */ 57 | @Test 58 | @Ignore 59 | public void k_simpleStream02() { 60 | 61 | List input = Arrays.asList( 62 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 63 | 64 | List result = null; // TODO 65 | 66 | assertThat(result) 67 | .containsExactly("ONE", "TWO", "THREE", "SIX", "SEVEN", "EIGHT", "TEN"); 68 | } 69 | 70 | /** 71 | * Given a list of words, create an output list that contains 72 | * only words from 3 to 8. 73 | * Use the collect(Collectors.toList()) pattern to create the output list. 74 | */ 75 | @Test 76 | @Ignore 77 | public void k_simpleStream03() { 78 | 79 | List input = Arrays.asList( 80 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 81 | 82 | List result = null; // TODO 83 | 84 | assertThat(result) 85 | .containsExactly("three", "four", "five", "six", "seven", "eight"); 86 | } 87 | 88 | /** 89 | * Given a list of words, create an output list that contains 90 | * only the first letters of all the words, without any double. 91 | * Use the collect(Collectors.toList()) pattern to create the output list. 92 | */ 93 | @Test 94 | @Ignore 95 | public void k_simpleStream04() { 96 | 97 | List input = Arrays.asList( 98 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 99 | 100 | List result = null; // TODO 101 | 102 | assertThat(result) 103 | .containsExactly("o", "t", "f", "s", "e", "n"); 104 | } 105 | 106 | /** 107 | * Given a list of words, create an output list that contains 108 | * only the first letters of all the words, without any double, sorted in the alphabetical order. 109 | * Use the collect(Collectors.toList()) pattern to create the output list. 110 | */ 111 | @Test 112 | @Ignore 113 | public void k_simpleStream05() { 114 | 115 | List input = Arrays.asList( 116 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 117 | 118 | List result = null; // TODO 119 | 120 | assertThat(result) 121 | .containsExactly("e", "f", "n", "o", "s", "t"); 122 | } 123 | 124 | /** 125 | * Given a list of words, count the number of different lengths of those words. 126 | * Try not to create any list. 127 | */ 128 | @Test 129 | @Ignore 130 | public void k_simpleStream06() { 131 | 132 | List input = Arrays.asList( 133 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 134 | 135 | long result = 0L; // TODO 136 | 137 | assertThat(result).isEqualTo(3L); 138 | } 139 | 140 | /** 141 | * Create the following list: {"+", "+", "+", "+", "+"}. 142 | * Try to use a factory method from Stream. 143 | */ 144 | @Test 145 | @Ignore 146 | public void k_simpleStream07() { 147 | 148 | List result = null; // TODO 149 | 150 | assertThat(result).containsExactly("+", "+", "+", "+", "+"); 151 | } 152 | 153 | /** 154 | * Create the following list: {"+++", "++++", "+++++", "+++++++", "++++++++"}. 155 | * Try to use a factory method from Stream. 156 | */ 157 | @Test 158 | @Ignore 159 | public void k_simpleStream08() { 160 | 161 | List result = null; // TODO 162 | 163 | assertThat(result).containsExactly("+++", "++++", "+++++", "++++++", "+++++++"); 164 | } 165 | 166 | /** 167 | * Create the following list: {1, 2, 3, 4, 5}. 168 | * Try to avoid the boxing of integers until the list is created. 169 | */ 170 | @Test 171 | @Ignore 172 | public void k_simpleStream09() { 173 | 174 | List result = null; // TODO 175 | 176 | assertThat(result).containsExactly(1, 2, 3, 4, 5); 177 | } 178 | 179 | /** 180 | * Create a function that take a String as a parameter and returns 181 | * the list of the letters of that string, in lower case, ordered in alphabetical order 182 | * and with no doubles. 183 | */ 184 | @Test 185 | @Ignore 186 | public void k_simpleStream10() { 187 | 188 | Function> wordToLetters = null; // TODO 189 | 190 | assertThat(wordToLetters.apply("Hello world")).containsExactly("d", "e", "h", "l", "o", "r", "w"); 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/D_Streams/L_HarderStreams.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.D_Streams; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Ignore; 22 | import org.junit.Test; 23 | 24 | import java.io.BufferedReader; 25 | import java.io.IOException; 26 | import java.nio.charset.StandardCharsets; 27 | import java.nio.file.Files; 28 | import java.nio.file.Paths; 29 | import java.util.Arrays; 30 | import java.util.List; 31 | import java.util.regex.Pattern; 32 | 33 | import static org.assertj.core.api.Assertions.assertThat; 34 | 35 | /** 36 | * This set of exercises covers harder stream pipelines, 37 | * including intermediate operations and collectors. 38 | *

39 | * Some of these exercises use a BufferedReader variable 40 | * named "reader" that the test has set up for you. 41 | */ 42 | public class L_HarderStreams { 43 | 44 | /** 45 | * Count the number of lines in the text file. 46 | *

47 | * Remember to use the BufferedReader named "reader" that has already been 48 | * opened for you. 49 | */ 50 | @Test 51 | @Ignore 52 | public void l_harderStream01() { 53 | 54 | long count = 0; // TODO 55 | 56 | assertThat(count).isEqualTo(14); 57 | } 58 | 59 | /** 60 | * Find the length of the longest line in the text file. 61 | *

62 | * Remember to use the BufferedReader named "reader" that has already been 63 | * opened for you. 64 | */ 65 | @Test 66 | @Ignore 67 | public void l_harderStream02() { 68 | 69 | int longestLength = 0; // TODO 70 | 71 | assertThat(longestLength).isEqualTo(53); 72 | } 73 | 74 | /** 75 | * Find the longest line in the text file. 76 | *

77 | * Remember to use the BufferedReader named "reader" that has already been 78 | * opened for you. 79 | */ 80 | @Test 81 | @Ignore 82 | public void l_harderStream03() { 83 | 84 | String longestLine = null; // TODO 85 | 86 | assertThat(longestLine).isEqualTo("Feed'st thy light's flame with self-substantial fuel,"); 87 | } 88 | 89 | /** 90 | * Select one of the longest words from the input list. 91 | */ 92 | @Test 93 | @Ignore 94 | public void l_harderStream04() { 95 | 96 | List input = Arrays.asList( 97 | "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"); 98 | 99 | String result = null; // TODO 100 | 101 | assertThat(result).isIn("charlie", "foxtrot"); 102 | } 103 | 104 | /** 105 | * Create a list of all the letters used in the following list, ordered in the alphabetical order 106 | * and with no doubles. 107 | * You can use a variant of the function created for K_SimpleStreams.simpleStream10(). 108 | */ 109 | @Test 110 | @Ignore 111 | public void l_harderStream05() { 112 | 113 | List input = Arrays.asList( 114 | "alfa", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel"); 115 | 116 | List result = null; // TODO 117 | 118 | assertThat(result).containsExactly("a", "b", "c", "d", "e", "f", "g", "h", "i", "l", "o", "r", "t", "v", "x"); 119 | } 120 | 121 | /** 122 | * Collect all the words from the text file into a list. 123 | *

124 | * Remember to use the BufferedReader named "reader" that has already been 125 | * opened for you. 126 | * Use the regular expression Pattern SPLIT_PATTERN to split a string into words, and use 127 | * Pattern.splitAsStream(String) to do the splitting. SPLIT_PATTERN is defined at the bottom of this file. 128 | * As before, use the BufferedReader variable named "reader" that has been set up for you to read from 129 | * the text file. 130 | */ 131 | @Test 132 | @Ignore 133 | public void l_harderStream06() { 134 | 135 | List output = null; // TODO 136 | 137 | assertThat(output).isEqualTo( 138 | Arrays.asList( 139 | "From", "fairest", "creatures", "we", "desire", "increase", 140 | "That", "thereby", "beauty's", "rose", "might", "never", "die", 141 | "But", "as", "the", "riper", "should", "by", "time", "decease", 142 | "His", "tender", "heir", "might", "bear", "his", "memory", 143 | "But", "thou", "contracted", "to", "thine", "own", "bright", "eyes", 144 | "Feed'st", "thy", "light's", "flame", "with", "self", "substantial", "fuel", 145 | "Making", "a", "famine", "where", "abundance", "lies", 146 | "Thy", "self", "thy", "foe", "to", "thy", "sweet", "self", "too", "cruel", 147 | "Thou", "that", "art", "now", "the", "world's", "fresh", "ornament", 148 | "And", "only", "herald", "to", "the", "gaudy", "spring", 149 | "Within", "thine", "own", "bud", "buriest", "thy", "content", 150 | "And", "tender", "churl", "mak'st", "waste", "in", "niggarding", 151 | "Pity", "the", "world", "or", "else", "this", "glutton", "be", 152 | "To", "eat", "the", "world's", "due", "by", "the", "grave", "and", "thee")); 153 | } 154 | 155 | /** 156 | * Read the words from the text file, and create a list containing the words 157 | * of length 8 or longer, converted to lower case, and sorted alphabetically. 158 | *

159 | * Remember to use the BufferedReader named "reader" that has already been 160 | * opened for you. 161 | */ 162 | @Test 163 | @Ignore 164 | public void l_harderStream07() { 165 | 166 | List output = null; // TODO 167 | 168 | assertThat(output).isEqualTo( 169 | Arrays.asList( 170 | "abundance", "beauty's", "contracted", "creatures", 171 | "increase", "niggarding", "ornament", "substantial")); 172 | } 173 | 174 | /** 175 | * Read the words from the text file, and create a list containing the words 176 | * of length 8 or longer, converted to lower case, and sorted reverse alphabetically. 177 | * (Same as above except for reversed sort order.) 178 | */ 179 | @Test 180 | @Ignore 181 | public void l_harderStream08() { 182 | 183 | List output = null; // TODO 184 | 185 | assertThat(output).isEqualTo( 186 | Arrays.asList( 187 | "substantial", "ornament", "niggarding", "increase", 188 | "creatures", "contracted", "beauty's", "abundance")); 189 | } 190 | 191 | /** 192 | * Read words from the text file, and sort unique, lower-cased words by length, 193 | * then alphabetically within length, and place the result into an output list. 194 | *

195 | * Remember to use the BufferedReader named "reader" that has already been 196 | * opened for you. 197 | */ 198 | @Test 199 | @Ignore 200 | public void l_harderStream09() { 201 | 202 | List output = null; // TODO 203 | 204 | assertThat(output).isEqualTo( 205 | Arrays.asList( 206 | "a", "as", "be", "by", "in", "or", "to", "we", 207 | "and", "art", "bud", "but", "die", "due", "eat", "foe", 208 | "his", "now", "own", "the", "thy", "too", "bear", "else", 209 | "eyes", "from", "fuel", "heir", "lies", "only", 210 | "pity", "rose", "self", "that", "thee", "this", "thou", 211 | "time", "with", "churl", "cruel", "flame", "fresh", "gaudy", 212 | "grave", "might", "never", "riper", "sweet", "thine", 213 | "waste", "where", "world", "bright", "desire", "famine", 214 | "herald", "mak'st", "making", "memory", "should", "spring", 215 | "tender", "within", "buriest", "content", "decease", 216 | "fairest", "feed'st", "glutton", "light's", "thereby", "world's", "beauty's", 217 | "increase", "ornament", "abundance", "creatures", "contracted", "niggarding", 218 | "substantial")); 219 | } 220 | 221 | 222 | // ======================================================== 223 | // END OF EXERCISES 224 | // TEST INFRASTRUCTURE IS BELOW 225 | // ======================================================== 226 | 227 | // Pattern for splitting a string into words 228 | static final Pattern SPLIT_PATTERN = Pattern.compile("[- .:,]+"); 229 | 230 | private BufferedReader reader; 231 | 232 | @Before 233 | public void z_setUpBufferedReader() throws IOException { 234 | reader = Files.newBufferedReader( 235 | Paths.get("files/Sonnet.txt"), StandardCharsets.UTF_8); 236 | } 237 | 238 | @After 239 | public void z_closeBufferedReader() throws IOException { 240 | reader.close(); 241 | } 242 | } 243 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/D_Streams/M_Reductions.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.D_Streams; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Ignore; 22 | import org.junit.Test; 23 | 24 | import java.io.BufferedReader; 25 | import java.io.IOException; 26 | import java.math.BigInteger; 27 | import java.nio.charset.StandardCharsets; 28 | import java.nio.file.Files; 29 | import java.nio.file.Paths; 30 | import java.util.List; 31 | import java.util.function.Consumer; 32 | import java.util.function.Predicate; 33 | import java.util.regex.Pattern; 34 | import java.util.stream.Collectors; 35 | import java.util.stream.IntStream; 36 | 37 | import static org.assertj.core.api.Assertions.assertThat; 38 | 39 | /** 40 | * This set of exercises covers the reduction step. 41 | *

42 | * Some of these exercises use a BufferedReader variable 43 | * named "reader" that the test has set up for you. 44 | */ 45 | public class M_Reductions { 46 | 47 | /** 48 | * Compute the sums of the 10 first integers starting with 1. 49 | */ 50 | @Test 51 | @Ignore 52 | public void m_reduction01() { 53 | 54 | int sum = 0; // TODO 55 | 56 | assertThat(sum).isEqualTo(55); 57 | } 58 | 59 | /** 60 | * Compute the factorial of 21. This number is quite large. 61 | */ 62 | @Test 63 | @Ignore 64 | public void m_reduction02() { 65 | 66 | BigInteger result = BigInteger.ONE; // TODO 67 | 68 | assertThat(result).isEqualTo(new BigInteger("51090942171709440000")); 69 | } 70 | 71 | /** 72 | * Given a a list of Consumer, create a single consumer that will pass the 73 | * element it consumes to all the elements of the list. 74 | * Try to use a method reference in your solution. 75 | * The given list contains 10 consumers of StringBuilder. Each of this consumer 76 | * just adds 1..9 to the content of the StringBuilder. 77 | */ 78 | @Test 79 | @Ignore 80 | public void m_reduction03() { 81 | 82 | List> consumers = 83 | IntStream.range(1, 10) 84 | .mapToObj(index -> (Consumer) (sb -> sb.append(index))) 85 | .collect(Collectors.toList()); 86 | 87 | Consumer consumer = null; // TODO 88 | 89 | StringBuilder sb = new StringBuilder("Hello"); 90 | consumer.accept(sb); 91 | 92 | assertThat(sb.toString()).isEqualTo("Hello123456789"); 93 | } 94 | 95 | /** 96 | * Given a a list of Predicates, create a single predicate that will be true if one predicate of the list 97 | * is true. 98 | * Try to use a method reference in your solution. 99 | * The given list contains 10 predicates, each of them tests if the index 1..9 is contained in the 100 | * tested String. 101 | */ 102 | @Test 103 | @Ignore 104 | public void m_reduction04() { 105 | 106 | List> predicates = 107 | IntStream.range(1, 10) 108 | .mapToObj(String::valueOf) 109 | .map(index -> (Predicate) (s -> s.contains(index))) 110 | .collect(Collectors.toList()); 111 | 112 | Predicate predicate = null; // TODO 113 | 114 | assertThat(predicate.test("Hello 01")).isTrue(); 115 | assertThat(predicate.test("Hello")).isFalse(); 116 | } 117 | 118 | /** 119 | * Get the last word in the text file. 120 | *

121 | * Remember to use the BufferedReader named "reader" that has already been 122 | * opened for you. 123 | */ 124 | @Test 125 | @Ignore 126 | public void m_reduction05() { 127 | 128 | String result = null; // TODO 129 | 130 | assertThat(result).isEqualTo("thee"); 131 | } 132 | 133 | 134 | // ======================================================== 135 | // END OF EXERCISES 136 | // TEST INFRASTRUCTURE IS BELOW 137 | // ======================================================== 138 | 139 | // Pattern for splitting a string into words 140 | static final Pattern SPLIT_PATTERN = Pattern.compile("[- .:,]+"); 141 | 142 | private BufferedReader reader; 143 | 144 | @Before 145 | public void z_setUpBufferedReader() throws IOException { 146 | reader = Files.newBufferedReader( 147 | Paths.get("files/Sonnet.txt"), StandardCharsets.UTF_8); 148 | } 149 | 150 | @After 151 | public void z_closeBufferedReader() throws IOException { 152 | reader.close(); 153 | } 154 | } 155 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/D_Streams/N_Challenges.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.D_Streams; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Ignore; 22 | import org.junit.Test; 23 | 24 | import java.io.BufferedReader; 25 | import java.io.IOException; 26 | import java.nio.charset.StandardCharsets; 27 | import java.nio.file.Files; 28 | import java.nio.file.Paths; 29 | import java.util.*; 30 | import java.util.regex.Pattern; 31 | import java.util.stream.Collector; 32 | import java.util.stream.Collectors; 33 | import java.util.stream.IntStream; 34 | import java.util.stream.Stream; 35 | 36 | import static org.assertj.core.api.Assertions.assertThat; 37 | 38 | public class N_Challenges { 39 | 40 | /** 41 | * Given a stream of strings, accumulate (collect) them into the result string 42 | * by inserting the input string at both the beginning and end. For example, given 43 | * input strings "x" and "y" the result should be "yxxy". Note: the input stream 44 | * is a parallel stream, so you MUST write a proper combiner function to get the 45 | * correct result. 46 | */ 47 | @Test 48 | @Ignore 49 | public void p_challenge01() { 50 | 51 | Stream input = Arrays.asList( 52 | "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", 53 | "k", "l", "m", "n", "o", "p", "q", "r", "s", "t") 54 | .parallelStream(); 55 | 56 | String result = input.collect(null, null, null).toString(); 57 | // TODO fill in lambda expressions or method references in place of the nulls in the line above. 58 | 59 | assertThat(result).isEqualTo("tsrqponmlkjihgfedcbaabcdefghijklmnopqrst"); 60 | } 61 | 62 | /** 63 | * Count the total number of words and the number of distinct, lower case 64 | * words in a stream, in one pass. This exercise uses a helper class 65 | * that defines methods that are called by the Stream.collect() method. 66 | * Your task is to fill in the implementation of the accumulate() and 67 | * combine() methods in the helper class. You don't need to modify the 68 | * test method itself. 69 | *

70 | * The stream is run in parallel, so you must write a combine() method 71 | * that works properly. 72 | */ 73 | static class TotalAndDistinct { 74 | private int count = 0; 75 | private final Set set = new HashSet<>(); 76 | 77 | // rely on implicit no-arg constructor 78 | 79 | void accumulate(String s) { 80 | // TODO write code to accumulate a single string into this object 81 | } 82 | 83 | void combine(TotalAndDistinct other) { 84 | // TODO write code to combine the other object into this one 85 | } 86 | 87 | int getTotalCount() { 88 | return count; 89 | } 90 | 91 | int getDistinctCount() { 92 | return set.size(); 93 | } 94 | } 95 | 96 | @Test 97 | @Ignore 98 | public void p_challenge02() { 99 | 100 | List allWords = sonnetReader.lines() 101 | .map(String::toLowerCase) 102 | .flatMap(SPLIT_PATTERN::splitAsStream) 103 | .collect(Collectors.toList()); 104 | 105 | TotalAndDistinct totalAndDistinct = 106 | Collections.nCopies(100, allWords) 107 | .parallelStream() 108 | .flatMap(List::stream) 109 | .collect(TotalAndDistinct::new, 110 | TotalAndDistinct::accumulate, 111 | TotalAndDistinct::combine); 112 | 113 | assertThat(totalAndDistinct.getDistinctCount()).isEqualTo(81); 114 | assertThat(totalAndDistinct.getTotalCount()).isEqualTo(10700); 115 | } 116 | 117 | 118 | /** 119 | * Denormalize this map. The input is a map whose keys are the number of legs of an animal 120 | * and whose values are lists of names of animals. Run through the map and generate a 121 | * "denormalized" list of strings describing the animal, with the animal's name separated 122 | * by a colon from the number of legs it has. The ordering in the output list is not 123 | * considered significant. 124 | *

125 | * Input is Map>: 126 | * { 4=["ibex", "hedgehog", "wombat"], 127 | * 6=["ant", "beetle", "cricket"], 128 | * ... 129 | * } 130 | *

131 | * Output should be a List: 132 | * [ "ibex:4", 133 | * "hedgehog:4", 134 | * "wombat:4", 135 | * "ant:6", 136 | * "beetle:6", 137 | * "cricket:6", 138 | * ... 139 | * ] 140 | */ 141 | @Test 142 | @Ignore 143 | public void p_challenge03() { 144 | 145 | Map> input = new HashMap<>(); 146 | input.put(4, Arrays.asList("ibex", "hedgehog", "wombat")); 147 | input.put(6, Arrays.asList("ant", "beetle", "cricket")); 148 | input.put(8, Arrays.asList("octopus", "spider", "squid")); 149 | input.put(10, Arrays.asList("crab", "lobster", "scorpion")); 150 | input.put(750, Arrays.asList("millipede")); 151 | 152 | List result = null; // TODO 153 | 154 | assertThat(result).hasSize(13); 155 | assertThat(result).contains( 156 | "ibex:4", "hedgehog:4", "wombat:4", "ant:6", "beetle:6", "cricket:6", 157 | "octopus:8", "spider:8", "squid:8", "crab:10", "lobster:10", "scorpion:10", 158 | "millipede:750"); 159 | } 160 | 161 | /** 162 | * Invert a "multi-map". (From an idea by Paul Sandoz) 163 | *

164 | * Given a Map>, convert it to Map>. 165 | * Each set member of the input map's values becomes a key in 166 | * the result map. Each key in the input map becomes a set member 167 | * of the values of the result map. In the input map, an item 168 | * may appear in the value set of multiple keys. In the result 169 | * map, that item will be a key, and its value set will be 170 | * its corresponding keys from the input map. 171 | *

172 | * In this case the input is Map> 173 | * and the result is Map>. 174 | *

175 | * For example, if the input map is 176 | * {p=[10, 20], q=[20, 30]} 177 | * then the result map should be 178 | * {10=[p], 20=[p, q], 30=[q]} 179 | * irrespective of ordering. Note that the Integer 20 appears 180 | * in the value sets for both p and q in the input map. Therefore, 181 | * in the result map, there should be a mapping with 20 as the key 182 | * and p and q as its value set. 183 | *

184 | * It is possible to accomplish this task using a single stream 185 | * pipeline (not counting nested B_streams), that is, in a single pass 186 | * over the input, without storing anything in a temporary collection. 187 | */ 188 | @Test 189 | @Ignore 190 | public void p_challenge04() { 191 | 192 | Map> input = new HashMap<>(); 193 | input.put("a", new HashSet<>(Arrays.asList(1, 2))); 194 | input.put("b", new HashSet<>(Arrays.asList(2, 3))); 195 | input.put("c", new HashSet<>(Arrays.asList(1, 3))); 196 | input.put("d", new HashSet<>(Arrays.asList(1, 4))); 197 | input.put("e", new HashSet<>(Arrays.asList(2, 4))); 198 | input.put("f", new HashSet<>(Arrays.asList(3, 4))); 199 | 200 | Map> result = null; // TODO 201 | 202 | assertThat(result).hasSize(4); 203 | assertThat(result.get(1)).contains("a", "c", "d"); 204 | assertThat(result.get(2)).contains("a", "b", "e"); 205 | assertThat(result.get(3)).contains("b", "c", "f"); 206 | assertThat(result.get(4)).contains("d", "e", "f"); 207 | } 208 | 209 | /** 210 | * Select the longest words from an input stream. That is, select the words 211 | * whose lengths are equal to the maximum word length. For this exercise, 212 | * you must compute the result in a single pass over the input stream. 213 | * The type of the input is a Stream, so you cannot access elements at random. 214 | * The stream is run in parallel, so the combiner function must be correct. 215 | */ 216 | @Test 217 | @Ignore 218 | public void p_challenge05() { 219 | 220 | Stream input = Stream.of( 221 | "alfa", "bravo", "charlie", "delta", 222 | "echo", "foxtrot", "golf", "hotel").parallel(); 223 | 224 | List result = input.collect( 225 | Collector.of(null, null, null, null)); 226 | // TODO implement a collector by replacing the nulls above 227 | 228 | 229 | assertThat(result).containsExactly("charlie", "foxtrot"); 230 | } 231 | 232 | /** 233 | * Given a string, split it into a list of strings consisting of 234 | * consecutive characters from the original string. Note: this is 235 | * similar to Python's itertools.groupby function, but it differs 236 | * from Java's Collectors.groupingBy() collector. 237 | */ 238 | @Test 239 | @Ignore 240 | public void p_challenge06() { 241 | 242 | String input = "aaaaabbccccdeeeeeeaaafff"; 243 | 244 | List result = null; // TODO 245 | 246 | assertThat(result).containsExactly("aaaaa", "bb", "cccc", "d", "eeeeee", "aaa", "fff"); 247 | } 248 | 249 | /** 250 | * Given a parallel stream of strings, collect them into a collection in reverse order. 251 | * Since the stream is parallel, you MUST write a proper combiner function in order to get 252 | * the correct result. 253 | */ 254 | @Test 255 | @Ignore 256 | public void p_challenge07() { 257 | 258 | Stream input = 259 | IntStream.range(0, 100).mapToObj(String::valueOf).parallel(); 260 | List expectedResult = 261 | IntStream.range(0, 100) 262 | .map(i -> 99 - i) 263 | .mapToObj(String::valueOf) 264 | .collect(Collectors.toList()); 265 | 266 | List result = 267 | input.collect(Collector.of(null, null, null)); 268 | // TODO fill in collector functions above 269 | 270 | assertThat(result).containsExactlyElementsOf(expectedResult); 271 | } 272 | 273 | 274 | /** 275 | * Given an array of int, find the int value that occurs a majority 276 | * of times in the array (that is, strictly more than half of the 277 | * elements are that value), and return that int value in an OptionalInt. 278 | * Note, return the majority int value, not the number of times it occurs. 279 | * If there is no majority value, return an empty OptionalInt. 280 | *

281 | * For example, given an input array [11, 12, 12] the result should be 282 | * an OptionalInt containing 12. Given an input array [11, 12, 13] 283 | * the result should be an empty OptionalInt. 284 | */ 285 | 286 | OptionalInt majority(int[] array) { 287 | return null; // TODO 288 | } 289 | 290 | @Test 291 | @Ignore 292 | public void p_challenge08() { 293 | 294 | int[] array1 = {13, 13, 24, 35, 24, 24, 35, 24, 24}; 295 | int[] array2 = {13, 13, 24, 35, 24, 24, 35, 24}; 296 | 297 | OptionalInt result1 = majority(array1); 298 | OptionalInt result2 = majority(array2); 299 | 300 | 301 | assertThat(result1).isEqualTo(OptionalInt.of(24)); 302 | assertThat(result2).isEmpty(); 303 | } 304 | 305 | 306 | /** 307 | * Create the following String with the people from the people.txt file. 308 | *

309 | * Remember to use the BufferedReader named "peopleReader" that has already been 310 | * opened for you. 311 | */ 312 | @Test 313 | @Ignore 314 | public void p_challenge09() { 315 | 316 | String expectedResult = "23: Barbara, Mary, Patricia, Susan\n" + 317 | "24: Sarah, Thomas, William\n" + 318 | "25: Linda, Richard\n" + 319 | "26: John, Margaret, Robert\n" + 320 | "27: Charles, David, Jennifer, Joseph, Michael\n" + 321 | "28: Elizabeth, James, Jessica"; 322 | 323 | String result = null; // TODO 324 | 325 | assertThat(result).isEqualTo(expectedResult); 326 | } 327 | 328 | // ======================================================== 329 | // END OF EXERCISES 330 | // TEST INFRASTRUCTURE IS BELOW 331 | // ======================================================== 332 | 333 | 334 | // Pattern for splitting a string into words 335 | static final Pattern SPLIT_PATTERN = Pattern.compile("[- .:,]+"); 336 | 337 | private BufferedReader sonnetReader; 338 | private BufferedReader peopleReader; 339 | 340 | @Before 341 | public void z_setUpBufferedReader() throws IOException { 342 | sonnetReader = Files.newBufferedReader( 343 | Paths.get("files/Sonnet.txt"), StandardCharsets.UTF_8); 344 | peopleReader = Files.newBufferedReader( 345 | Paths.get("files/people.txt"), StandardCharsets.UTF_8); 346 | } 347 | 348 | @After 349 | public void z_closeBufferedReader() throws IOException { 350 | sonnetReader.close(); 351 | peopleReader.close(); 352 | } 353 | } 354 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/D_Streams/model/Person.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.D_Streams.model; 18 | 19 | import java.util.Objects; 20 | 21 | public class Person { 22 | 23 | private String name; 24 | private int age; 25 | 26 | public Person() { 27 | 28 | } 29 | 30 | public Person(String name, int age) { 31 | this.name = name; 32 | this.age = age; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public void setName(String name) { 40 | this.name = name; 41 | } 42 | 43 | public int getAge() { 44 | return age; 45 | } 46 | 47 | public void setAge(int age) { 48 | this.age = age; 49 | } 50 | 51 | @Override 52 | public String toString() { 53 | return "Person{" + 54 | "name='" + name + '\'' + 55 | ", age=" + age + 56 | '}'; 57 | } 58 | 59 | @Override 60 | public boolean equals(Object o) { 61 | if (this == o) return true; 62 | if (o == null || getClass() != o.getClass()) return false; 63 | Person person = (Person) o; 64 | return age == person.age && 65 | name.equals(person.name); 66 | } 67 | 68 | @Override 69 | public int hashCode() { 70 | return Objects.hash(name, age); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/E_Collectors/O_SimpleCollectors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.E_Collectors; 18 | 19 | import org.junit.Ignore; 20 | import org.junit.Test; 21 | 22 | import java.util.Arrays; 23 | import java.util.List; 24 | 25 | import static org.assertj.core.api.Assertions.assertThat; 26 | 27 | /** 28 | * This set of exercises covers the collect() terminal operation with the basic collectors. 29 | * The collectors used in this class can be built from the factory methods of the Collectors 30 | * factory class. This collectors are the simplest ones: they do not take another, so-called 31 | * downstream collector as a parameter. 32 | */ 33 | public class O_SimpleCollectors { 34 | 35 | /** 36 | * Count the number of elements on that list. 37 | * Try to use a collector from the Collectors factory class. 38 | */ 39 | @Test 40 | @Ignore 41 | public void n_simpleCollector01() { 42 | 43 | List input = Arrays.asList( 44 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 45 | 46 | long count = 0L; // TODO 47 | 48 | assertThat(count).isEqualTo(10L); 49 | } 50 | 51 | /** 52 | * Compute the max element of that list, in the alphabetical order. 53 | * Try to use a collector from the Collectors factory class. 54 | */ 55 | @Test 56 | @Ignore 57 | public void n_simpleCollector02() { 58 | 59 | List input = Arrays.asList( 60 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 61 | 62 | String max = null; // TODO 63 | 64 | assertThat(max).isEqualTo("two"); 65 | } 66 | 67 | /** 68 | * Compute the min length of the elements of that list. 69 | * Try to use a collector from the Collectors factory class. 70 | */ 71 | @Test 72 | @Ignore 73 | public void n_simpleCollector03() { 74 | 75 | List input = Arrays.asList( 76 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 77 | 78 | int minLength = 0; // TODO 79 | 80 | assertThat(minLength).isEqualTo(3); 81 | } 82 | 83 | /** 84 | * Compute the average length of the elements of that list. 85 | * Try to use a collector from the Collectors factory class. 86 | */ 87 | @Test 88 | @Ignore 89 | public void n_simpleCollector04() { 90 | 91 | List input = Arrays.asList( 92 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 93 | 94 | double averageLength = 0; // TODO 95 | 96 | assertThat(averageLength).isEqualTo(3.9d); 97 | } 98 | 99 | /** 100 | * Compute the sum of the elements of that list. 101 | * Try to use a collector from the Collectors factory class. 102 | */ 103 | @Test 104 | @Ignore 105 | public void n_simpleCollector05() { 106 | 107 | List input = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); 108 | 109 | int sum = 0; // TODO 110 | 111 | assertThat(sum).isEqualTo(45); 112 | } 113 | 114 | /** 115 | * Concatenate the elements of that list in a String, separated by a space. 116 | * Try to use a collector from the Collectors factory class. 117 | */ 118 | @Test 119 | @Ignore 120 | public void n_simpleCollector06() { 121 | 122 | List input = Arrays.asList( 123 | "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"); 124 | 125 | String result = null; // TODO 126 | 127 | assertThat(result).isEqualTo("one two three four five six seven eight nine ten"); 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/E_Collectors/P_HarderCollectors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.E_Collectors; 18 | 19 | import org.junit.After; 20 | import org.junit.Before; 21 | import org.junit.Ignore; 22 | import org.junit.Test; 23 | 24 | import java.io.BufferedReader; 25 | import java.io.IOException; 26 | import java.nio.charset.StandardCharsets; 27 | import java.nio.file.Files; 28 | import java.nio.file.Paths; 29 | import java.util.List; 30 | import java.util.Map; 31 | import java.util.Random; 32 | import java.util.regex.Pattern; 33 | import java.util.stream.IntStream; 34 | 35 | import static org.assertj.core.api.Assertions.assertThat; 36 | import static org.junit.Assert.assertEquals; 37 | 38 | /** 39 | * This set of exercises covers the collect() terminal operation with the complex collectors. 40 | *

41 | * Some of these exercises use a BufferedReader variable 42 | * named "reader" that the test has set up for you. 43 | */ 44 | public class P_HarderCollectors { 45 | 46 | 47 | /** 48 | * Categorize the words from the text file into a map, where the map's key 49 | * is the length of each word, and the value corresponding to a key is a 50 | * list of words of that length. Don't bother with uniqueness or lower- 51 | * casing the words. 52 | *

53 | * As before, use the BufferedReader variable named 54 | * "reader" that has been set up for you to read from the text file, and 55 | * use SPLIT_PATTERN for splitting the line into words. 56 | */ 57 | @Test 58 | @Ignore 59 | public void o_harderCollector01() { 60 | 61 | Map> result = null; // TODO 62 | 63 | assertThat(result).hasSize(11); 64 | assertThat(result.get(8)).containsExactly("increase", "beauty's", "ornament"); 65 | assertThat(result.get(9)).containsExactly("creatures", "abundance"); 66 | assertThat(result.get(10)).containsExactly("contracted", "niggarding"); 67 | assertThat(result.get(11)).containsExactly("substantial"); 68 | } 69 | 70 | 71 | /** 72 | * Categorize the words from the text file into a map, where the map's key 73 | * is the length of each word, and the value corresponding to a key is a 74 | * count of words of that length. Don't bother with uniqueness or lower- 75 | * casing the words. 76 | *

77 | * This is the same as the previous exercise except 78 | * the map values are the count of words instead of a list of words. 79 | */ 80 | @Test 81 | @Ignore 82 | public void o_harderCollector02() { 83 | 84 | Map result = null; // TODO 85 | 86 | assertThat(result).hasSize(11); 87 | assertThat(result.get(1)).isEqualTo(1L); 88 | assertThat(result.get(2)).isEqualTo(11L); 89 | assertThat(result.get(3)).isEqualTo(28L); 90 | assertThat(result.get(4)).isEqualTo(21L); 91 | assertThat(result.get(5)).isEqualTo(16L); 92 | assertThat(result.get(6)).isEqualTo(12L); 93 | assertThat(result.get(7)).isEqualTo(10L); 94 | assertThat(result.get(8)).isEqualTo(3L); 95 | assertThat(result.get(9)).isEqualTo(2L); 96 | assertThat(result.get(10)).isEqualTo(2L); 97 | assertThat(result.get(11)).isEqualTo(1L); 98 | } 99 | 100 | 101 | /** 102 | * Gather the words from the text file into a map, accumulating a count of 103 | * the number of occurrences of each word. Don't worry about upper case and 104 | * lower case. 105 | *

106 | * Extra challenge: implement two solutions, one that uses 107 | * groupingBy() and the other that uses toMap(). 108 | */ 109 | @Test 110 | @Ignore 111 | public void o_harderCollector03() { 112 | 113 | Map result = null; // TODO 114 | 115 | assertThat(result).hasSize(87); 116 | assertThat(result.get("tender")).isEqualTo(2L); 117 | assertThat(result.get("the")).isEqualTo(6L); 118 | assertThat(result.get("churl")).isEqualTo(1L); 119 | assertThat(result.get("thine")).isEqualTo(2L); 120 | assertThat(result.get("world")).isEqualTo(1L); 121 | assertThat(result.get("thy")).isEqualTo(4L); 122 | assertThat(result.get("self")).isEqualTo(3L); 123 | } 124 | 125 | /** 126 | * Gather all the letters used to write the Sonnet in lower case, and find one of the least used. 127 | *

128 | * Remember to use the BufferedReader named "reader" that has already been 129 | * opened for you. 130 | *

131 | * You can use a variant of the function created for K_SimpleStreams.simpleStream10(). 132 | */ 133 | @Test 134 | @Ignore 135 | public void o_harderCollector04() { 136 | 137 | String leastUsedLetter = null; // TODO 138 | 139 | assertThat(leastUsedLetter).isIn("v", "k"); 140 | } 141 | 142 | /** 143 | * Gather all the letters used to write the Sonnet in lower case, and find all the least used in a list. 144 | *

145 | * Remember to use the BufferedReader named "reader" that has already been 146 | * opened for you. 147 | *

148 | * You can use a variant of the function created for K_SimpleStreams.simpleStream10(). 149 | */ 150 | @Test 151 | @Ignore 152 | public void o_harderCollector05() { 153 | 154 | List leastUsedLetters = null; // TODO 155 | 156 | assertThat(leastUsedLetters).hasSize(2); 157 | assertThat(leastUsedLetters).contains("v", "k"); 158 | } 159 | 160 | 161 | /** 162 | * From the words in the text file, create nested maps, where the outer map is a 163 | * map from the first letter of the word to an inner map. (Use a string of length 164 | * one as the key.) The inner map, in turn, is a mapping from the length of the 165 | * word to a list of words with that length. Don't bother with any lowercasing 166 | * or uniquifying of the words. 167 | *

168 | * For example, given the words "foo bar baz bazz foo" the string 169 | * representation of the result would be: 170 | * {b={3=[bar, baz], 4=[bazz]}, f={3=[foo, foo]}} 171 | */ 172 | @Test 173 | @Ignore 174 | public void o_harderCollector06() { 175 | 176 | Map>> result = null; // TODO 177 | 178 | assertThat(result).hasSize(25); 179 | assertThat(result.get("a").get(9).toString()).isEqualTo("[abundance]"); 180 | assertThat(result.get("b").get(2).toString()).isEqualTo("[by, be, by]"); 181 | assertThat(result.get("f").get(5).toString()).isEqualTo("[flame, fresh]"); 182 | assertThat(result.get("g").get(5).toString()).isEqualTo("[gaudy, grave]"); 183 | assertThat(result.get("s").get(6).toString()).isEqualTo("[should, spring]"); 184 | assertThat(result.get("s").get(11).toString()).isEqualTo("[substantial]"); 185 | assertThat(result.get("t").get(3).toString()).isEqualTo("[the, thy, thy, thy, too, the, the, thy, the, the, the]"); 186 | assertThat(result.get("w").get(5).toString()).isEqualTo("[where, waste, world]"); 187 | } 188 | 189 | 190 | /** 191 | * Given a stream of integers, compute separate sums of the even and odd values 192 | * in this stream. Since the input is a stream, this necessitates making a single 193 | * pass over the input. 194 | */ 195 | @Test 196 | @Ignore 197 | public void o_harderCollector07() { 198 | 199 | IntStream input = new Random(987523).ints(20, 0, 100); 200 | 201 | int sumEvens = 0; // TODO 202 | int sumOdds = 0; // TODO 203 | 204 | assertEquals(516, sumEvens); 205 | assertEquals(614, sumOdds); 206 | } 207 | 208 | 209 | // ======================================================== 210 | // END OF EXERCISES 211 | // TEST INFRASTRUCTURE IS BELOW 212 | // ======================================================== 213 | 214 | 215 | // Pattern for splitting a string into words 216 | static final Pattern SPLIT_PATTERN = Pattern.compile("[- .:,]+"); 217 | 218 | private BufferedReader reader; 219 | 220 | @Before 221 | public void z_setUpBufferedReader() throws IOException { 222 | reader = Files.newBufferedReader( 223 | Paths.get("files/Sonnet.txt"), StandardCharsets.UTF_8); 224 | } 225 | 226 | @After 227 | public void z_closeBufferedReader() throws IOException { 228 | reader.close(); 229 | } 230 | } 231 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/F_Challenges/ActorsAndMoviesChallenge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.F_Challenges; 18 | 19 | import org.junit.Before; 20 | import org.junit.Ignore; 21 | import org.junit.Test; 22 | import org.paumard.codeone2019.F_Challenges.model.Actor; 23 | import org.paumard.codeone2019.F_Challenges.model.Movie; 24 | 25 | import java.io.BufferedReader; 26 | import java.io.FileInputStream; 27 | import java.io.IOException; 28 | import java.io.InputStreamReader; 29 | import java.util.Set; 30 | import java.util.function.Function; 31 | import java.util.stream.Collectors; 32 | import java.util.stream.Stream; 33 | import java.util.zip.GZIPInputStream; 34 | 35 | import static org.assertj.core.api.Assertions.assertThat; 36 | 37 | 38 | /** 39 | * In this challenge, you are going to analyze a database of movies. Each movies has several properties: 40 | * a release year, a title, and the set of the actors that played in that movie. An Actor has a first name 41 | * and a last name. There are almost 14k movies in the base. 42 | *

43 | * You can check the Movie class and the Actor class for more information. 44 | */ 45 | public class ActorsAndMoviesChallenge { 46 | 47 | private Set movies; 48 | 49 | 50 | /** 51 | * This first test is free and is only here to make sure that everything is ok with the data files. 52 | */ 53 | @Test 54 | @Ignore 55 | public void actorsAndMovies00() { 56 | 57 | assertThat(movies).hasSize(13891); 58 | } 59 | 60 | /** 61 | * From the set of movies, it should not be too hard to count the number of actors. 62 | */ 63 | @Test 64 | @Ignore 65 | public void actorsAndMovies01() { 66 | 67 | long numberOfActors = 0L; // TODO 68 | 69 | assertThat(numberOfActors).isEqualTo(168727L); 70 | } 71 | 72 | /** 73 | * First, count the number of release years in this file. 74 | */ 75 | @Test 76 | @Ignore 77 | public void actorsAndMovies02() { 78 | 79 | long numberOfRelaseYears = 0L; // TODO 80 | 81 | assertThat(numberOfRelaseYears).isEqualTo(76L); 82 | } 83 | 84 | /** 85 | * Second, find the earliest year and the last year in this file. 86 | * Try to do it in one pass over the data. 87 | */ 88 | @Test 89 | @Ignore 90 | public void actorsAndMovies03() { 91 | 92 | int firstYear = 0; // TODO 93 | int lastYear = 0; // TODO 94 | 95 | assertThat(firstYear).isEqualTo(1916); 96 | assertThat(lastYear).isEqualTo(2004); 97 | } 98 | 99 | /** 100 | * Third, find the year that saw the greatest number of released movies, along 101 | * with the number of movie released. 102 | */ 103 | @Test 104 | @Ignore 105 | public void actorsAndMovies04() { 106 | 107 | int year = 0; // TODO 108 | long numberOfMovies = 0L; // TODO 109 | 110 | assertThat(year).isEqualTo(1997); 111 | assertThat(numberOfMovies).isEqualTo(678L); 112 | } 113 | 114 | /** 115 | * Fourth, find the movie with the greatest number of actors in it. Hint: there is only one. 116 | */ 117 | @Test 118 | @Ignore 119 | public void actorsAndMovies05() { 120 | 121 | int maxNumberOfActors = 0; // TODO 122 | String title = null; // TODO 123 | 124 | assertThat(maxNumberOfActors).isEqualTo(238); 125 | assertThat(title).isEqualTo("Malcolm X"); 126 | } 127 | 128 | /** 129 | * Then, find the actor that played in the greatest number of movies. 130 | */ 131 | @Test 132 | @Ignore 133 | public void actorsAndMovies06() { 134 | 135 | Actor mostSeenActor = null; // TODO 136 | long numberOfMoviePlayed = 0L; // TODO 137 | 138 | assertThat(mostSeenActor).isEqualTo(new Actor("Welker", "Frank")); 139 | assertThat(numberOfMoviePlayed).isEqualTo(90L); 140 | } 141 | 142 | /** 143 | * A little harder: try to find the actor that played in the greatest number of movies 144 | * during a year. 145 | *

146 | * There are several ways to use the Stream API to get the result. The most elegant is to use a Collector. 147 | * Try to solve the actorsAndMovies06 challenge using a single collector. You will have to use several 148 | * methods from the Collectors factory class, and use collectingAndThen(). 149 | *

150 | * Once you have this collector, you can use it as a downstream collector of another, well-known 151 | * collector 152 | *

153 | * Using a collector is possible only with the Collectors methods added in Java 9. 154 | */ 155 | @Test 156 | @Ignore 157 | public void actorsAndMovies07() { 158 | 159 | int year = 0; // TODO 160 | Actor mostSeenActor = null; // TODO 161 | long numberOfMoviePlayed = 0L; 162 | 163 | assertThat(year).isEqualTo(1999); 164 | assertThat(mostSeenActor).isEqualTo(new Actor("Hawn", "Phil")); 165 | assertThat(numberOfMoviePlayed).isEqualTo(24); 166 | } 167 | 168 | /** 169 | * Create now a stream of Map.Entry<Actor, Actor> with all the actors that played together. Since we want 170 | * unique pairs, you should make sure that in a pair, the actors are ordered alphabetically. That is, the following 171 | * stream: 172 | *

173 | * A B C D 174 | *

175 | * should generate the following stream of pairs: 176 | *

177 | * {A, B} {A, C} {A, D} {B, C} {B, D} {C, D} 178 | *

179 | * You may find useful to create a Comparator of Actors to achieve that. 180 | *

181 | * What is the total number of such pairs? What is the number of unique pairs? 182 | */ 183 | @Test 184 | @Ignore 185 | public void actorsAndMovies08() { 186 | 187 | long totalNumberOfPairs = 0L; // TODO 188 | long numberOfUniquePairs = 0L; // TODO 189 | 190 | assertThat(totalNumberOfPairs).isEqualTo(7616029L); 191 | assertThat(numberOfUniquePairs).isEqualTo(7487873L); 192 | } 193 | 194 | /** 195 | * The (almost) last step is to find the two actors that played the most together. Look carefully at the code 196 | * you are writing. Since there are 170k actors in the base, that could make 14 billions of potential couples. 197 | * You clearly do not want to compute that! 198 | *

199 | * You may use the stream you create in the previous step. 200 | */ 201 | @Test 202 | @Ignore 203 | public void actorsAndMovies09() { 204 | 205 | long number = 0L; 206 | Actor actor1 = null; // TODO 207 | Actor actor2 = null; // TODO 208 | 209 | assertThat(number).isEqualTo(15L); 210 | assertThat(actor1).isEqualTo(new Actor("Howard", "Clint")); 211 | assertThat(actor2).isEqualTo(new Actor("Howard", "Rance")); 212 | } 213 | 214 | /** 215 | * The (real) last step is to find the two actors that played the most together during a year. The approach is the 216 | * same as previously: try to create a collector and use it as a downstream collector. 217 | */ 218 | @Test 219 | @Ignore 220 | public void actorsAndMovies10() { 221 | 222 | int year = 0; // TODO 223 | long number = 0L; // TODO 224 | Actor actor1 = null; // TODO 225 | Actor actor2 = null; // TODO 226 | 227 | assertThat(year).isEqualTo(1995); 228 | assertThat(number).isEqualTo(5L); 229 | assertThat(actor1).isEqualTo(new Actor("Ingham", "Barrie")); 230 | assertThat(actor2).isEqualTo(new Actor("Webster", "Derek")); 231 | } 232 | 233 | 234 | // ======================================================== 235 | // END OF EXERCISES 236 | // TEST INFRASTRUCTURE IS BELOW 237 | // ======================================================== 238 | 239 | @Before 240 | public void z_setupData() { 241 | 242 | Function> toMovie = 243 | line -> { 244 | String[] elements = line.split("/"); 245 | String title = elements[0].substring(0, elements[0].lastIndexOf("(")).trim(); 246 | String releaseYear = elements[0].substring(elements[0].lastIndexOf("(") + 1, elements[0].lastIndexOf(")")); 247 | if (releaseYear.contains(",")) { 248 | // Movies with a coma in their title are discarded 249 | return Stream.empty(); 250 | } 251 | Movie movie = new Movie(title, Integer.valueOf(releaseYear)); 252 | 253 | 254 | for (int i = 1; i < elements.length; i++) { 255 | String[] name = elements[i].split(", "); 256 | String lastName = name[0].trim(); 257 | String firstName = ""; 258 | if (name.length > 1) { 259 | firstName = name[1].trim(); 260 | } 261 | 262 | Actor actor = new Actor(lastName, firstName); 263 | movie.addActor(actor); 264 | } 265 | return Stream.of(movie); 266 | }; 267 | 268 | try (FileInputStream fis = new FileInputStream("files/movies/movies-mpaa.txt.gz"); 269 | GZIPInputStream gzis = new GZIPInputStream(fis); 270 | InputStreamReader reader = new InputStreamReader(gzis); 271 | BufferedReader bufferedReader = new BufferedReader(reader); 272 | Stream lines = bufferedReader.lines(); 273 | ) { 274 | 275 | movies = lines.flatMap(toMovie).collect(Collectors.toSet()); 276 | 277 | } catch (IOException e) { 278 | System.out.println("e.getMessage() = " + e.getMessage()); 279 | } 280 | } 281 | } 282 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/F_Challenges/ShakespeareChallenge.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.F_Challenges; 18 | 19 | import org.junit.Before; 20 | import org.junit.Ignore; 21 | import org.junit.Test; 22 | 23 | import java.io.*; 24 | import java.util.List; 25 | import java.util.Map; 26 | import java.util.Set; 27 | import java.util.function.Function; 28 | import java.util.stream.Collectors; 29 | import java.util.zip.GZIPInputStream; 30 | 31 | import static org.assertj.core.api.Assertions.assertThat; 32 | 33 | /** 34 | * Many information are missing on Shakespeare's life, and it is said, even if it cannot be sure, 35 | * that he was a great Scrabble player. 36 | *

37 | * The goal of this challenge is to measure how good a player he was. 38 | *

39 | * Several elements are given: first, the list of all the words he used in his writings, second the 40 | * list of all the allowed words at Scrabble, in english. Two arrays are also given: the first one 41 | * gives the score for each letter, and the second one the number of available letters in the game. 42 | */ 43 | public class ShakespeareChallenge { 44 | 45 | private static final int[] scrabbleENScore = { 46 | // a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z 47 | 1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10}; 48 | 49 | private static final int[] scrabbleENDistribution = { 50 | // a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z 51 | 9, 2, 2, 1, 12, 2, 3, 2, 9, 1, 1, 4, 2, 6, 8, 2, 1, 6, 4, 6, 4, 2, 2, 1, 2, 1}; 52 | 53 | private Set scrabbleWords; 54 | private Set shakespeareWords; 55 | 56 | /** 57 | * This first test is free and is only here to make sure that everything is ok with the data files. 58 | */ 59 | @Test 60 | @Ignore 61 | public void shakespeare01() { 62 | 63 | assertThat(scrabbleWords).hasSize(23688); 64 | assertThat(shakespeareWords).hasSize(79339); 65 | } 66 | 67 | /** 68 | * First, compute the number of words allowed at Scrabble Shakespeare used. 69 | */ 70 | @Test 71 | @Ignore 72 | public void shakespeare02() { 73 | 74 | long number = 0L; // TODO 75 | 76 | assertThat(number).isEqualTo(14277L); 77 | } 78 | 79 | /** 80 | * Second, compute a function that can compute the score of a given word. 81 | */ 82 | @Test 83 | @Ignore 84 | public void shakespeare03() { 85 | 86 | Function score = null; // TODO 87 | 88 | assertThat(score.apply("hello")).isEqualTo(8); 89 | assertThat(score.apply("world")).isEqualTo(9); 90 | } 91 | 92 | /** 93 | * Third, get the best words that Shakespeare could have played. 94 | */ 95 | @Test 96 | @Ignore 97 | public void shakespeare04() { 98 | 99 | int bestScore = 0; // TODO 100 | List bestWords = null; // TODO 101 | 102 | assertThat(bestScore).isEqualTo(33); 103 | assertThat(bestWords).containsExactly("whizzing"); 104 | } 105 | 106 | /** 107 | * The best word looks a little suspect, is it really possible to write 108 | * such a word, given that there is only on 'z' available in the game? 109 | * We need to check if the word can be written given the available letters 110 | * in the game. 111 | *

112 | * First, let us create a function that takes a word, and returns 113 | * the histogram of the letters in that word 114 | */ 115 | @Test 116 | @Ignore 117 | public void shakespeare05() { 118 | 119 | Function> numberOfLettersUsed = null; // TODO 120 | 121 | assertThat(numberOfLettersUsed.apply("hello")) 122 | .containsOnly(Map.entry("h", 1L), Map.entry("e", 1L), Map.entry("l", 2L), Map.entry("o", 1L)); 123 | assertThat(numberOfLettersUsed.apply("whizzing")) 124 | .containsOnly(Map.entry("w", 1L), Map.entry("h", 1L), Map.entry("i", 2L), 125 | Map.entry("z", 2L), Map.entry("n", 1L), Map.entry("g", 1L)); 126 | } 127 | 128 | /** 129 | * Second, create a Function, that computes the number of blanks you need to 130 | * write a word. You can use the previous function and scrabbleENDistribution. 131 | * This array gives the available letters in the game. 132 | */ 133 | @Test 134 | @Ignore 135 | public void shakespeare06() { 136 | 137 | Function numberOfBlanks = null; // TODO 138 | 139 | assertThat(numberOfBlanks.apply("hello")).isEqualTo(0); 140 | assertThat(numberOfBlanks.apply("whizzing")).isEqualTo(1L); 141 | assertThat(numberOfBlanks.apply("buzzards")).isEqualTo(1L); 142 | } 143 | 144 | /** 145 | * Remember that a blank letter does not score any point. So you need to update the scoring 146 | * function. Write the new scoring function, taking into account that some letters are blanks. 147 | */ 148 | @Test 149 | @Ignore 150 | public void shakespeare07() { 151 | 152 | Function scoreWithBlank = null; // TODO 153 | 154 | assertThat(scoreWithBlank.apply("hello")).isEqualTo(8); 155 | assertThat(scoreWithBlank.apply("whizzing")).isEqualTo(23); 156 | } 157 | 158 | /** 159 | * You can now recompute the best word, taking into account the available letters 160 | * in the game and the new scoring function. 161 | */ 162 | @Test 163 | @Ignore 164 | public void shakespeare08() { 165 | 166 | int bestScore = 0; // TODO 167 | List bestWords = null; // TODO 168 | 169 | assertThat(bestScore).isEqualTo(26); 170 | assertThat(bestWords).containsExactly("squeezes"); 171 | } 172 | 173 | /** 174 | * What about getting the words that would score 24? Do not forget to sort 175 | * them in the alphabetical order. 176 | */ 177 | @Test 178 | @Ignore 179 | public void shakespeare09() { 180 | 181 | List wordsOfScore24 = null; 182 | 183 | assertThat(wordsOfScore24).containsExactly("exequies", "joyfully", "quaffing", "wheezing", "zephyrs"); 184 | } 185 | 186 | /** 187 | * Now that we have the best words, we need to place them on the Scrabble board. The first move has to 188 | * touch the central square, and since the board is symmetrical, playing on a line is the same as playing 189 | * on a column. 190 | *

191 | * The line you must play on is the following: TW . . DL . . . C . . . DL . . TW 192 | *

193 | * Where TW stands for Triple Word score (you cannot use this square on the first move), DL Double Letter score, 194 | * and C Center. The word you put on the board must have one letter on the C square, and can then have a letter on 195 | * one of the DL square. 196 | *

197 | * Knowing that you draw 7 letters, that placing all the letters brings a 50 points bonus, and that the first 198 | * move gets a double word score, what would Shakespeare have scored? We ask for the 4 best scores, and their 199 | * corresponding words. 200 | */ 201 | @Test 202 | @Ignore 203 | public void shakespeare10() { 204 | 205 | Map> bestWordsByScore = null; 206 | 207 | assertThat(bestWordsByScore).hasSize(4); 208 | assertThat(bestWordsByScore).containsKeys(114, 116, 118, 120); 209 | assertThat(bestWordsByScore.get(114)).contains("qualify", "quicker", "quicken"); 210 | assertThat(bestWordsByScore.get(116)).contains("equinox"); 211 | assertThat(bestWordsByScore.get(118)).contains("zephyrs"); 212 | assertThat(bestWordsByScore.get(120)).contains("jezebel", "quickly"); 213 | } 214 | 215 | 216 | // ======================================================== 217 | // END OF EXERCISES 218 | // TEST INFRASTRUCTURE IS BELOW 219 | // ======================================================== 220 | 221 | @Before 222 | public void z_setupData() { 223 | 224 | try (InputStream fileInputStream = new FileInputStream("files/shakespeare/words.shakespeare.txt.gz"); 225 | GZIPInputStream gzipInputStream = new GZIPInputStream(fileInputStream); 226 | InputStreamReader reader = new InputStreamReader(gzipInputStream); 227 | BufferedReader bufferedReader = new BufferedReader(reader); 228 | ) { 229 | scrabbleWords = bufferedReader.lines().map(String::toLowerCase).collect(Collectors.toSet()); 230 | } catch (IOException e) { 231 | e.printStackTrace(); 232 | } 233 | try (InputStream fileInputStream = new FileInputStream("files/shakespeare/ospd.txt.gz"); 234 | GZIPInputStream gzipInputStream = new GZIPInputStream(fileInputStream); 235 | InputStreamReader reader = new InputStreamReader(gzipInputStream); 236 | BufferedReader bufferedReader = new BufferedReader(reader); 237 | ) { 238 | shakespeareWords = bufferedReader.lines().map(String::toLowerCase).collect(Collectors.toSet()); 239 | } catch (IOException e) { 240 | e.printStackTrace(); 241 | } 242 | } 243 | } 244 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/F_Challenges/model/Actor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.F_Challenges.model; 18 | 19 | import java.util.Objects; 20 | 21 | public class Actor { 22 | public String lastName, firstName ; 23 | 24 | public Actor(String lastName, String firstName) { 25 | this.lastName = lastName; 26 | this.firstName = firstName; 27 | } 28 | 29 | public String lastName() { 30 | return this.lastName ; 31 | } 32 | 33 | public String firstName() { 34 | return this.firstName ; 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | int hash = 7; 40 | hash = 67 * hash + Objects.hashCode(this.lastName); 41 | hash = 67 * hash + Objects.hashCode(this.firstName); 42 | return hash; 43 | } 44 | 45 | @Override 46 | public boolean equals(Object obj) { 47 | if (obj == null) { 48 | return false; 49 | } 50 | if (getClass() != obj.getClass()) { 51 | return false; 52 | } 53 | final Actor other = (Actor) obj; 54 | if (!Objects.equals(this.lastName, other.lastName)) { 55 | return false; 56 | } 57 | return Objects.equals(this.firstName, other.firstName); 58 | } 59 | 60 | @Override 61 | public String toString() { 62 | return "Actor{" + "lastName=" + lastName + ", firstName=" + firstName + '}'; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/test/java/org/paumard/codeone2019/F_Challenges/model/Movie.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2019 José Paumard 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package org.paumard.codeone2019.F_Challenges.model; 18 | 19 | import java.util.HashSet; 20 | import java.util.Set; 21 | 22 | public class Movie { 23 | private String title ; 24 | private int releaseYear ; 25 | 26 | private Set actors = new HashSet<>() ; 27 | 28 | public Movie(String title, int releaseYear) { 29 | this.title = title; 30 | this.releaseYear = releaseYear; 31 | } 32 | 33 | public String title() { 34 | return this.title ; 35 | } 36 | 37 | public int releaseYear() { 38 | return this.releaseYear ; 39 | } 40 | 41 | public void addActor(Actor actor) { 42 | this.actors.add(actor) ; 43 | } 44 | 45 | public Set actors() { 46 | return this.actors ; 47 | } 48 | 49 | @Override 50 | public String toString() { 51 | return "Movie{" + "title=" + title + ", releaseYear=" + releaseYear + ", actors=" + actors + '}'; 52 | } 53 | } 54 | --------------------------------------------------------------------------------