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);
+ }
+}