From e8148f06c4bf5e064b84d4bbdb3e99d6987f0741 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:55:47 +0000 Subject: [PATCH] feature: align build to Java 11, add test suite, CI, and code-quality fixes Co-Authored-By: Bobby Nobakht --- .github/workflows/build.yml | 26 ++++++++++ .gitignore | 2 + README.md | 19 +++---- pom.xml | 16 +++--- .../chap1/FilteringApples.java | 16 +++--- .../chap10/ReadPositiveIntParam.java | 21 -------- .../java/lambdasinaction/chap11/Util.java | 11 +---- .../chap1/FilteringApplesTest.java | 49 +++++++++++++++++++ .../chap10/ReadPositiveIntParamTest.java | 30 ++++++++++++ .../java/lambdasinaction/chap11/UtilTest.java | 15 ++++++ 10 files changed, 149 insertions(+), 56 deletions(-) create mode 100644 .github/workflows/build.yml create mode 100644 src/test/java/lambdasinaction/chap1/FilteringApplesTest.java create mode 100644 src/test/java/lambdasinaction/chap10/ReadPositiveIntParamTest.java create mode 100644 src/test/java/lambdasinaction/chap11/UtilTest.java diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 00000000..1d6adc2e --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,26 @@ +name: build + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up JDK 11 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '11' + cache: maven + + - name: Compile + run: mvn -B compile + + - name: Test + run: mvn -B test diff --git a/.gitignore b/.gitignore index b7d7ac33..d83e7f88 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ /target /local +dependency-reduced-pom.xml # Eclipse, Netbeans and IntelliJ files /.* !.gitignore +!.github /nbproject /*.ipr /*.iws diff --git a/README.md b/README.md index 9ee848d5..fe034a4b 100644 --- a/README.md +++ b/README.md @@ -29,17 +29,18 @@ The source code for all examples can be found in the directory [src/main/java/la * Appendix D: Lambdas and JVM bytecode We will update the repository as we update the book. Stay tuned! -### Make sure to have JDK8 installed -The latest binary can be found here: http://www.oracle.com/technetwork/java/javase/overview/java8-2100321.html +### Make sure to have JDK 11 (or newer) installed +The 2nd-edition examples use APIs introduced after Java 8 (e.g. `Optional.or`, `Optional.stream`, +`Collectors.flatMapping`/`filtering`, `Stream.takeWhile`), so the project targets Java 11 +(`maven.compiler.release=11` in `pom.xml`). A JDK 11 or later distribution is required to build. +You can download a JDK from [Eclipse Temurin (Adoptium)](https://adoptium.net/) or +[Oracle Java](https://www.oracle.com/java/technologies/downloads/). $ java -version -java version "1.8.0_05" -Java(TM) SE Runtime Environment (build 1.8.0_05-b13) -Java HotSpot(TM) 64-Bit Server VM (build 25.5-b02, mixed mode) - - -You can download a preview version here: https://jdk8.java.net/ +openjdk version "11.0.22" 2024-01-16 +OpenJDK Runtime Environment (build 11.0.22+7) +OpenJDK 64-Bit Server VM (build 11.0.22+7, mixed mode) ### Compile/Run the examples Using maven: @@ -55,5 +56,5 @@ Alternatively you can compile the files manually inside the directory src/main/j You can also import the project in your favorite IDE: * In IntelliJ use "File->Open" menu and navigate to the folder where the project resides - * In Eclipse use "File->Import->Existing Maven Projects" (also modify "Reduntant super interfaces" to report as Warnings instead of Errors + * In Eclipse use "File->Import->Existing Maven Projects" (also modify "Redundant super interfaces" to report as Warnings instead of Errors * In Netbeans use "File->Open Project" menu \ No newline at end of file diff --git a/pom.xml b/pom.xml index 10e5035e..d322f786 100644 --- a/pom.xml +++ b/pom.xml @@ -10,23 +10,26 @@ UTF-8 + 11 + 1.37 org.openjdk.jmh jmh-core - 1.17.4 + ${jmh.version} org.openjdk.jmh jmh-generator-annprocess - 1.17.4 + ${jmh.version} junit junit - 4.11 + 4.13.2 + test @@ -35,15 +38,12 @@ org.apache.maven.plugins maven-compiler-plugin - 3.1 - - 1.9 - 1.9 - + 3.13.0 org.apache.maven.plugins maven-shade-plugin + 3.5.3 package diff --git a/src/main/java/lambdasinaction/chap1/FilteringApples.java b/src/main/java/lambdasinaction/chap1/FilteringApples.java index 51afc8cb..33567df0 100644 --- a/src/main/java/lambdasinaction/chap1/FilteringApples.java +++ b/src/main/java/lambdasinaction/chap1/FilteringApples.java @@ -9,26 +9,26 @@ public static void main(String ... args){ List inventory = Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), - new Apple(120, "red")); + new Apple(120, "red")); // [Apple{color='green', weight=80}, Apple{color='green', weight=155}] List greenApples = filterApples(inventory, FilteringApples::isGreenApple); System.out.println(greenApples); - + // [Apple{color='green', weight=155}] List heavyApples = filterApples(inventory, FilteringApples::isHeavyApple); System.out.println(heavyApples); - + // [Apple{color='green', weight=80}, Apple{color='green', weight=155}] List greenApples2 = filterApples(inventory, (Apple a) -> "green".equals(a.getColor())); System.out.println(greenApples2); - + // [Apple{color='green', weight=155}] List heavyApples2 = filterApples(inventory, (Apple a) -> a.getWeight() > 150); System.out.println(heavyApples2); - + // [] - List weirdApples = filterApples(inventory, (Apple a) -> a.getWeight() < 80 || + List weirdApples = filterApples(inventory, (Apple a) -> a.getWeight() < 80 || "brown".equals(a.getColor())); System.out.println(weirdApples); } @@ -54,7 +54,7 @@ public static List filterHeavyApples(List inventory){ } public static boolean isGreenApple(Apple apple) { - return "green".equals(apple.getColor()); + return "green".equals(apple.getColor()); } public static boolean isHeavyApple(Apple apple) { @@ -69,7 +69,7 @@ public static List filterApples(List inventory, Predicate p } } return result; - } + } public static class Apple { private int weight = 0; diff --git a/src/main/java/lambdasinaction/chap10/ReadPositiveIntParam.java b/src/main/java/lambdasinaction/chap10/ReadPositiveIntParam.java index acac12b9..b7580c46 100644 --- a/src/main/java/lambdasinaction/chap10/ReadPositiveIntParam.java +++ b/src/main/java/lambdasinaction/chap10/ReadPositiveIntParam.java @@ -1,32 +1,11 @@ package lambdasinaction.chap10; -import org.junit.*; - import java.util.*; import static java.util.Optional.*; -import static org.junit.Assert.assertEquals; public class ReadPositiveIntParam { - @Test - public void testMap() { - Properties props = new Properties(); - props.setProperty("a", "5"); - props.setProperty("b", "true"); - props.setProperty("c", "-3"); - - assertEquals(5, readDurationImperative(props, "a")); - assertEquals(0, readDurationImperative(props, "b")); - assertEquals(0, readDurationImperative(props, "c")); - assertEquals(0, readDurationImperative(props, "d")); - - assertEquals(5, readDurationWithOptional(props, "a")); - assertEquals(0, readDurationWithOptional(props, "b")); - assertEquals(0, readDurationWithOptional(props, "c")); - assertEquals(0, readDurationWithOptional(props, "d")); - } - public static int readDurationImperative(Properties props, String name) { String value = props.getProperty(name); if (value != null) { diff --git a/src/main/java/lambdasinaction/chap11/Util.java b/src/main/java/lambdasinaction/chap11/Util.java index a72c4d33..e589c3b7 100644 --- a/src/main/java/lambdasinaction/chap11/Util.java +++ b/src/main/java/lambdasinaction/chap11/Util.java @@ -25,20 +25,11 @@ public static void delay() { public static double format(double number) { synchronized (formatter) { - return new Double(formatter.format(number)); + return Double.parseDouble(formatter.format(number)); } } public static CompletableFuture> sequence(List> futures) { -/* - CompletableFuture allDoneFuture = - CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])); - return allDoneFuture.thenApply(v -> - futures.stream(). - map(future -> future.join()). - collect(Collectors.toList()) - ); -*/ return CompletableFuture.supplyAsync(() -> futures.stream(). map(future -> future.join()). collect(Collectors.toList())); diff --git a/src/test/java/lambdasinaction/chap1/FilteringApplesTest.java b/src/test/java/lambdasinaction/chap1/FilteringApplesTest.java new file mode 100644 index 00000000..f70e71dc --- /dev/null +++ b/src/test/java/lambdasinaction/chap1/FilteringApplesTest.java @@ -0,0 +1,49 @@ +package lambdasinaction.chap1; + +import org.junit.Test; + +import java.util.Arrays; +import java.util.List; + +import lambdasinaction.chap1.FilteringApples.Apple; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; + +public class FilteringApplesTest { + + private final List inventory = Arrays.asList( + new Apple(80, "green"), + new Apple(155, "green"), + new Apple(120, "red")); + + @Test + public void filterGreenApplesReturnsOnlyGreen() { + List green = FilteringApples.filterGreenApples(inventory); + assertEquals(2, green.size()); + assertTrue(green.stream().allMatch(a -> "green".equals(a.getColor()))); + } + + @Test + public void filterHeavyApplesReturnsApplesOver150() { + List heavy = FilteringApples.filterHeavyApples(inventory); + assertEquals(1, heavy.size()); + assertEquals(Integer.valueOf(155), heavy.get(0).getWeight()); + } + + @Test + public void filterApplesWithPredicate() { + List redApples = FilteringApples.filterApples(inventory, a -> "red".equals(a.getColor())); + assertEquals(1, redApples.size()); + assertEquals("red", redApples.get(0).getColor()); + } + + @Test + public void isGreenAppleAndIsHeavyApple() { + assertTrue(FilteringApples.isGreenApple(new Apple(50, "green"))); + assertFalse(FilteringApples.isGreenApple(new Apple(50, "red"))); + assertTrue(FilteringApples.isHeavyApple(new Apple(200, "red"))); + assertFalse(FilteringApples.isHeavyApple(new Apple(100, "red"))); + } +} diff --git a/src/test/java/lambdasinaction/chap10/ReadPositiveIntParamTest.java b/src/test/java/lambdasinaction/chap10/ReadPositiveIntParamTest.java new file mode 100644 index 00000000..1f1bfc50 --- /dev/null +++ b/src/test/java/lambdasinaction/chap10/ReadPositiveIntParamTest.java @@ -0,0 +1,30 @@ +package lambdasinaction.chap10; + +import org.junit.Test; + +import java.util.Properties; + +import static lambdasinaction.chap10.ReadPositiveIntParam.readDurationImperative; +import static lambdasinaction.chap10.ReadPositiveIntParam.readDurationWithOptional; +import static org.junit.Assert.assertEquals; + +public class ReadPositiveIntParamTest { + + @Test + public void testMap() { + Properties props = new Properties(); + props.setProperty("a", "5"); + props.setProperty("b", "true"); + props.setProperty("c", "-3"); + + assertEquals(5, readDurationImperative(props, "a")); + assertEquals(0, readDurationImperative(props, "b")); + assertEquals(0, readDurationImperative(props, "c")); + assertEquals(0, readDurationImperative(props, "d")); + + assertEquals(5, readDurationWithOptional(props, "a")); + assertEquals(0, readDurationWithOptional(props, "b")); + assertEquals(0, readDurationWithOptional(props, "c")); + assertEquals(0, readDurationWithOptional(props, "d")); + } +} diff --git a/src/test/java/lambdasinaction/chap11/UtilTest.java b/src/test/java/lambdasinaction/chap11/UtilTest.java new file mode 100644 index 00000000..c4005e17 --- /dev/null +++ b/src/test/java/lambdasinaction/chap11/UtilTest.java @@ -0,0 +1,15 @@ +package lambdasinaction.chap11; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; + +public class UtilTest { + + @Test + public void formatRoundsToTwoDecimals() { + assertEquals(3.14, Util.format(3.14159), 0.0001); + assertEquals(5.0, Util.format(5.0), 0.0001); + assertEquals(2.5, Util.format(2.5), 0.0001); + } +}