diff --git a/README.md b/README.md index 9ee848d5..61b981e0 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,37 @@ -Java8InAction -=============== -This repository contains all the source code for the examples and quizzes in the book Java 8 in Action: Lambdas, Streams and functional-style programming. + +Java 8 In Action +================ + +This repository contains all the source code for the examples and quizzes in the book +Java 8 in Action: Lambdas, Streams and functional-style programming. +λ演算,数据流操作,函数式编程。 You can purchase the book here: [http://manning.com/urma/](http://manning.com/urma/) or on Amazon The source code for all examples can be found in the directory [src/main/java/lambdasinaction](https://github.com/java8/Java8InAction/tree/master/src/main/java/lambdasinaction) -* Chapter 1: Java 8: why should you care? -* Chapter 2: Passing code with behavior parameterization -* Chapter 3: Lambda expressions -* Chapter 4: Working with Streams -* Chapter 5: Processing data with streams -* Chapter 6: Collecting data with streams -* Chapter 7: Parallel data processing and performance -* Chapter 8: Refactoring, testing, debugging -* Chapter 9: Default methods -* Chapter 10: Using Optional as a better alternative to null -* Chapter 11: CompletableFuture: composable asynchronous programming -* Chapter 12: New Date and Time API -* Chapter 13: Thinking functionally -* Chapter 14: Functional programming techniques -* Chapter 15: Blending OOP and FP: comparing Java 8 and Scala -* Chapter 16: Conclusions and "where next" for Java -* Appendix A: Miscellaneous language updates -* Appendix B: Miscellaneous library updates -* Appendix C: Performing multiple operations in parallel on a Stream -* Appendix D: Lambdas and JVM bytecode +* Chapter 1: Java 8: why should you care? / Java 8:你为什么要在乎? +* Chapter 2: Passing code with behavior parameterization / 传递具有参数化行为的代码 +* Chapter 3: Lambda expressions / λ表达式、匿名表达式、匿名函数 +* Chapter 4: Working with Streams / 数据流操作 +* Chapter 5: Processing data with streams / 处理数据流 +* Chapter 6: Collecting data with streams / 收集数据流 +* Chapter 7: Parallel data processing and performance / 数据并行处理和性能 +* Chapter 8: Refactoring, testing, debugging / 重构、测试、调试 +* Chapter 9: Default methods / 默认方法 +* Chapter 10: Using Optional as a better alternative to null / 使用Optional作为一个更好的null选择 +* Chapter 11: CompletableFuture: composable asynchronous programming / CompletableFuture:可组合的异步编程 +* Chapter 12: New Date and Time API / 新的日期和时间API +* Chapter 13: Thinking functionally / 功能思考 +* Chapter 14: Functional programming techniques / 函数式编程技术 +* Chapter 15: Blending OOP and FP: comparing Java 8 and Scala / 混合OOP和FP:比较Java 8和Scala +* Chapter 16: Conclusions and "where next" for Java / 结论和Java的未来 +* Appendix A: Miscellaneous language updates / 语言更新 +* Appendix B: Miscellaneous library updates / 包更新 +* Appendix C: Performing multiple operations in parallel on a Stream / 在数据流上并行执行多个操作 +* Appendix D: Lambdas and JVM bytecode / λ表达式和JVM字节码 + We will update the repository as we update the book. Stay tuned! ### Make sure to have JDK8 installed @@ -56,4 +61,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 Netbeans use "File->Open Project" menu \ No newline at end of file + * In Netbeans use "File->Open Project" menu + diff --git a/pom.xml b/pom.xml index 10e5035e..938e5fee 100644 --- a/pom.xml +++ b/pom.xml @@ -44,6 +44,7 @@ org.apache.maven.plugins maven-shade-plugin + 3.2.1 package diff --git a/src/main/java/lambdasinaction/chap1/FilteringApples.java b/src/main/java/lambdasinaction/chap1/FilteringApples.java index 51afc8cb..00d0b123 100644 --- a/src/main/java/lambdasinaction/chap1/FilteringApples.java +++ b/src/main/java/lambdasinaction/chap1/FilteringApples.java @@ -3,14 +3,18 @@ import java.util.*; import java.util.function.Predicate; +/** + * Chapter 1: Java 8: why should you care? / Java 8:你为什么要在乎? + */ public class FilteringApples{ 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); @@ -18,7 +22,8 @@ public static void main(String ... args){ // [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); @@ -33,8 +38,11 @@ public static void main(String ... args){ System.out.println(weirdApples); } + // JDK 7 之前版本写法 + public static List filterGreenApples(List inventory){ - List result = new ArrayList<>(); + List result = new ArrayList<>(inventory.size()); + // for-each for (Apple apple: inventory){ if ("green".equals(apple.getColor())) { result.add(apple); @@ -44,7 +52,7 @@ public static List filterGreenApples(List inventory){ } public static List filterHeavyApples(List inventory){ - List result = new ArrayList<>(); + List result = new ArrayList<>(inventory.size()); for (Apple apple: inventory){ if (apple.getWeight() > 150) { result.add(apple); @@ -53,6 +61,8 @@ public static List filterHeavyApples(List inventory){ return result; } + // 过滤操作函数 + public static boolean isGreenApple(Apple apple) { return "green".equals(apple.getColor()); } @@ -61,8 +71,16 @@ public static boolean isHeavyApple(Apple apple) { return apple.getWeight() > 150; } + // JDK 8 版本写法 + // 行为操作函数 + + /** + * @param inventory 苹果存货清单 + * @param p 过滤操作函数 + * @return 期望的苹果列表 + */ public static List filterApples(List inventory, Predicate p){ - List result = new ArrayList<>(); + List result = new ArrayList<>(inventory.size()); for(Apple apple : inventory){ if(p.test(apple)){ result.add(apple); @@ -72,8 +90,8 @@ public static List filterApples(List inventory, Predicate p } public static class Apple { - private int weight = 0; - private String color = ""; + private final int weight; + private final String color; public Apple(int weight, String color){ this.weight = weight; @@ -84,18 +102,11 @@ public Integer getWeight() { return weight; } - public void setWeight(Integer weight) { - this.weight = weight; - } - public String getColor() { return color; } - public void setColor(String color) { - this.color = color; - } - + @Override public String toString() { return "Apple{" + "color='" + color + '\'' + diff --git a/src/main/java/lambdasinaction/chap2/FilteringApples.java b/src/main/java/lambdasinaction/chap2/FilteringApples.java index 0f61fd08..6cb5c55b 100644 --- a/src/main/java/lambdasinaction/chap2/FilteringApples.java +++ b/src/main/java/lambdasinaction/chap2/FilteringApples.java @@ -2,12 +2,20 @@ import java.util.*; +/** + * Chapter 2: Passing code with behavior parameterization / 传递具有参数化行为的代码 + */ public class FilteringApples{ public static void main(String ... args){ - List inventory = Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red")); + List inventory = Arrays.asList( + new Apple(80,"green"), + new Apple(155, "green"), + new Apple(120, "red") + ); + // JDK 7 之前版本写法 // [Apple{color='green', weight=80}, Apple{color='green', weight=155}] List greenApples = filterApplesByColor(inventory, "green"); System.out.println(greenApples); @@ -28,18 +36,20 @@ public static void main(String ... args){ List redAndHeavyApples = filter(inventory, new AppleRedAndHeavyPredicate()); System.out.println(redAndHeavyApples); + // 匿名实现类对象(JDK 7 之前版本写法) // [Apple{color='red', weight=120}] List redApples2 = filter(inventory, new ApplePredicate() { public boolean test(Apple a){ - return a.getColor().equals("red"); + return "red".equals(a.getColor()); } }); System.out.println(redApples2); - } + // JDK 7 之前版本写法 + public static List filterGreenApples(List inventory){ - List result = new ArrayList<>(); + List result = new ArrayList<>(inventory.size()); for(Apple apple: inventory){ if("green".equals(apple.getColor())){ result.add(apple); @@ -49,7 +59,7 @@ public static List filterGreenApples(List inventory){ } public static List filterApplesByColor(List inventory, String color){ - List result = new ArrayList<>(); + List result = new ArrayList<>(inventory.size()); for(Apple apple: inventory){ if(apple.getColor().equals(color)){ result.add(apple); @@ -59,7 +69,7 @@ public static List filterApplesByColor(List inventory, String colo } public static List filterApplesByWeight(List inventory, int weight){ - List result = new ArrayList<>(); + List result = new ArrayList<>(inventory.size()); for(Apple apple: inventory){ if(apple.getWeight() > weight){ result.add(apple); @@ -70,7 +80,7 @@ public static List filterApplesByWeight(List inventory, int weight public static List filter(List inventory, ApplePredicate p){ - List result = new ArrayList<>(); + List result = new ArrayList<>(inventory.size()); for(Apple apple : inventory){ if(p.test(apple)){ result.add(apple); @@ -80,8 +90,8 @@ public static List filter(List inventory, ApplePredicate p){ } public static class Apple { - private int weight = 0; - private String color = ""; + private final int weight; + private final String color; public Apple(int weight, String color){ this.weight = weight; @@ -92,18 +102,10 @@ public Integer getWeight() { return weight; } - public void setWeight(Integer weight) { - this.weight = weight; - } - public String getColor() { return color; } - public void setColor(String color) { - this.color = color; - } - public String toString() { return "Apple{" + "color='" + color + '\'' + @@ -112,10 +114,19 @@ public String toString() { } } + // 函数式接口 + + /** + * 具体类型的过滤操作函数接口。 + * @see java.util.function.Predicate + */ + @FunctionalInterface interface ApplePredicate{ - public boolean test(Apple a); + boolean test(Apple a); } + // 谓词函数对象类 + static class AppleWeightPredicate implements ApplePredicate{ public boolean test(Apple apple){ return apple.getWeight() > 150; @@ -133,4 +144,4 @@ public boolean test(Apple apple){ && apple.getWeight() > 150; } } -} \ No newline at end of file +} diff --git a/src/main/java/lambdasinaction/chap2/MeaningOfThis.java b/src/main/java/lambdasinaction/chap2/MeaningOfThis.java index 88dfb8e0..94b87e2f 100644 --- a/src/main/java/lambdasinaction/chap2/MeaningOfThis.java +++ b/src/main/java/lambdasinaction/chap2/MeaningOfThis.java @@ -1,23 +1,30 @@ package lambdasinaction.chap2; -public class MeaningOfThis -{ +/** + * 变量作用域上下文 + * + * 类上下文,实例上下文 + */ +public class MeaningOfThis { public final int value = 4; - public void doIt() - { + + public void doIt() { int value = 6; + // 变量作用域上下文 Runnable r = new Runnable(){ public final int value = 5; public void run(){ int value = 10; + // this 引用匿名对象 System.out.println(this.value); } }; r.run(); } - public static void main(String...args) - { + + public static void main(String...args) { MeaningOfThis m = new MeaningOfThis(); + // 5 m.doIt(); // ??? } } diff --git a/src/main/java/lambdasinaction/chap3/ExecuteAround.java b/src/main/java/lambdasinaction/chap3/ExecuteAround.java index 6c15fb6a..2be44d2b 100644 --- a/src/main/java/lambdasinaction/chap3/ExecuteAround.java +++ b/src/main/java/lambdasinaction/chap3/ExecuteAround.java @@ -1,41 +1,43 @@ package lambdasinaction.chap3; import java.io.*; + public class ExecuteAround { - public static void main(String ...args) throws IOException{ + public static void main(String... args) throws IOException { - // method we want to refactor to make more flexible - String result = processFileLimited(); - System.out.println(result); + // method we want to refactor to make more flexible + String result = processFileLimited(); + System.out.println(result); - System.out.println("---"); + System.out.println("---"); + // BufferedReader::readLine String oneLine = processFile((BufferedReader b) -> b.readLine()); System.out.println(oneLine); String twoLines = processFile((BufferedReader b) -> b.readLine() + b.readLine()); System.out.println(twoLines); - } public static String processFileLimited() throws IOException { - try (BufferedReader br = - new BufferedReader(new FileReader("lambdasinaction/chap3/data.txt"))) { - return br.readLine(); - } + // try-with-resources + try (BufferedReader br = + new BufferedReader(new FileReader("lambdasinaction/chap3/data.txt"))) { + return br.readLine(); + } } public static String processFile(BufferedReaderProcessor p) throws IOException { - try(BufferedReader br = new BufferedReader(new FileReader("lambdasinaction/chap3/data.txt"))){ + // try-with-resources + try (BufferedReader br = + new BufferedReader(new FileReader("lambdasinaction/chap3/data.txt"))) { return p.process(br); } - } - public interface BufferedReaderProcessor{ - public String process(BufferedReader b) throws IOException; - + public interface BufferedReaderProcessor { + String process(BufferedReader b) throws IOException; } } diff --git a/src/main/java/lambdasinaction/chap3/Lambdas.java b/src/main/java/lambdasinaction/chap3/Lambdas.java index 697f340e..bdd5b1f8 100644 --- a/src/main/java/lambdasinaction/chap3/Lambdas.java +++ b/src/main/java/lambdasinaction/chap3/Lambdas.java @@ -2,21 +2,30 @@ import java.util.*; +/** + * Chapter 3: Lambda expressions / λ表达式、匿名表达式、匿名函数 + */ public class Lambdas { public static void main(String ...args){ - + // 匿名类对象 // Simple example Runnable r = () -> System.out.println("Hello!"); r.run(); // Filtering with lambdas - List inventory = Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red")); - - // [Apple{color='green', weight=80}, Apple{color='green', weight=155}] + List inventory = Arrays.asList( + new Apple(80,"green"), + new Apple(155, "green"), + new Apple(120, "red") + ); + + // 过滤操作函数 + // [Apple{color='green', weight=80}, Apple{color='green', weight=155}] List greenApples = filter(inventory, (Apple a) -> "green".equals(a.getColor())); System.out.println(greenApples); - + // 对象比较函数 + // Comparator.comparing(Apple::getWeight) Comparator c = (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight()); // [Apple{color='green', weight=80}, Apple{color='red', weight=120}, Apple{color='green', weight=155}] @@ -25,7 +34,7 @@ public static void main(String ...args){ } public static List filter(List inventory, ApplePredicate p){ - List result = new ArrayList<>(); + List result = new ArrayList<>(inventory.size()); for(Apple apple : inventory){ if(p.test(apple)){ result.add(apple); @@ -35,8 +44,8 @@ public static List filter(List inventory, ApplePredicate p){ } public static class Apple { - private int weight = 0; - private String color = ""; + private final int weight; + private final String color; public Apple(int weight, String color){ this.weight = weight; @@ -47,18 +56,11 @@ public Integer getWeight() { return weight; } - public void setWeight(Integer weight) { - this.weight = weight; - } - public String getColor() { return color; } - public void setColor(String color) { - this.color = color; - } - + @Override public String toString() { return "Apple{" + "color='" + color + '\'' + @@ -68,6 +70,6 @@ public String toString() { } interface ApplePredicate{ - public boolean test(Apple a); + boolean test(Apple a); } } \ No newline at end of file diff --git a/src/main/java/lambdasinaction/chap3/Sorting.java b/src/main/java/lambdasinaction/chap3/Sorting.java index 41acbe25..1234274f 100644 --- a/src/main/java/lambdasinaction/chap3/Sorting.java +++ b/src/main/java/lambdasinaction/chap3/Sorting.java @@ -1,15 +1,20 @@ package lambdasinaction.chap3; import java.util.*; -import static java.util.Comparator.comparing; +/** + * Chapter 3: Lambda expressions / λ表达式、匿名表达式、匿名函数 + */ public class Sorting { public static void main(String...args){ - // 1 - List inventory = new ArrayList<>(); - inventory.addAll(Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red"))); + // 1、比较器对象 + List inventory = new ArrayList<>(Arrays.asList( + new Apple(80, "green"), + new Apple(155, "green"), + new Apple(120, "red")) + ); // [Apple{color='green', weight=80}, Apple{color='red', weight=120}, Apple{color='green', weight=155}] inventory.sort(new AppleComparator()); @@ -18,7 +23,7 @@ public static void main(String...args){ // reshuffling things a little inventory.set(1, new Apple(30, "green")); - // 2 + // 2、比较器匿名对象 // [Apple{color='green', weight=30}, Apple{color='green', weight=80}, Apple{color='green', weight=155}] inventory.sort(new Comparator() { public int compare(Apple a1, Apple a2){ @@ -29,7 +34,7 @@ public int compare(Apple a1, Apple a2){ // reshuffling things a little inventory.set(1, new Apple(20, "red")); - // 3 + // 3、lambda表达式、匿名表达式 // [Apple{color='red', weight=20}, Apple{color='green', weight=30}, Apple{color='green', weight=155}] inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight())); System.out.println(inventory); @@ -37,15 +42,15 @@ public int compare(Apple a1, Apple a2){ // reshuffling things a little inventory.set(1, new Apple(10, "red")); - // 4 + // 4、匿名函数对象 // [Apple{color='red', weight=10}, Apple{color='red', weight=20}, Apple{color='green', weight=155}] - inventory.sort(comparing(Apple::getWeight)); + inventory.sort(Comparator.comparing(Apple::getWeight)); System.out.println(inventory); } public static class Apple { - private Integer weight = 0; - private String color = ""; + private final Integer weight; + private final String color; public Apple(Integer weight, String color){ this.weight = weight; @@ -56,18 +61,10 @@ public Integer getWeight() { return weight; } - public void setWeight(Integer weight) { - this.weight = weight; - } - public String getColor() { return color; } - public void setColor(String color) { - this.color = color; - } - public String toString() { return "Apple{" + "color='" + color + '\'' + @@ -76,6 +73,9 @@ public String toString() { } } + /** + * 苹果比较器 + */ static class AppleComparator implements Comparator { public int compare(Apple a1, Apple a2){ return a1.getWeight().compareTo(a2.getWeight()); diff --git a/src/main/java/lambdasinaction/chap4/Dish.java b/src/main/java/lambdasinaction/chap4/Dish.java index 96307644..b880a373 100644 --- a/src/main/java/lambdasinaction/chap4/Dish.java +++ b/src/main/java/lambdasinaction/chap4/Dish.java @@ -1,4 +1,5 @@ package lambdasinaction.chap4; + import java.util.*; public class Dish { @@ -31,7 +32,7 @@ public Type getType() { return type; } - public enum Type { MEAT, FISH, OTHER } + public enum Type {MEAT, FISH, OTHER} @Override public String toString() { @@ -39,13 +40,15 @@ public String toString() { } public static final List menu = - Arrays.asList( new Dish("pork", false, 800, Dish.Type.MEAT), - new Dish("beef", false, 700, Dish.Type.MEAT), - new Dish("chicken", false, 400, Dish.Type.MEAT), - new Dish("french fries", true, 530, Dish.Type.OTHER), - new Dish("rice", true, 350, Dish.Type.OTHER), - new Dish("season fruit", true, 120, Dish.Type.OTHER), - new Dish("pizza", true, 550, Dish.Type.OTHER), - new Dish("prawns", false, 400, Dish.Type.FISH), - new Dish("salmon", false, 450, Dish.Type.FISH)); -} \ No newline at end of file + Arrays.asList( + new Dish("pork", false, 800, Dish.Type.MEAT), + new Dish("beef", false, 700, Dish.Type.MEAT), + new Dish("chicken", false, 400, Dish.Type.MEAT), + new Dish("french fries", true, 530, Dish.Type.OTHER), + new Dish("rice", true, 350, Dish.Type.OTHER), + new Dish("season fruit", true, 120, Dish.Type.OTHER), + new Dish("pizza", true, 550, Dish.Type.OTHER), + new Dish("prawns", false, 400, Dish.Type.FISH), + new Dish("salmon", false, 450, Dish.Type.FISH) + ); +} diff --git a/src/main/java/lambdasinaction/chap4/StreamBasic.java b/src/main/java/lambdasinaction/chap4/StreamBasic.java index 19a8c176..a5c0589e 100644 --- a/src/main/java/lambdasinaction/chap4/StreamBasic.java +++ b/src/main/java/lambdasinaction/chap4/StreamBasic.java @@ -1,50 +1,56 @@ package lambdasinaction.chap4; -import java.util.*; -import java.util.stream.*; - -import static java.util.Comparator.comparing; -import static java.util.stream.Collectors.toList; - -import static lambdasinaction.chap4.Dish.menu; - +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Chapter 4: Working with Streams / 数据流操作 + */ public class StreamBasic { - public static void main(String...args){ + public static void main(String... args) { + // 实例方法函数对象 // Java 7 - getLowCaloricDishesNamesInJava7(Dish.menu).forEach(System.out::println); + getLowCaloricDishesNamesInJava7(Dish.menu) + .forEach(System.out::println); System.out.println("---"); // Java 8 - getLowCaloricDishesNamesInJava8(Dish.menu).forEach(System.out::println); + getLowCaloricDishesNamesInJava8(Dish.menu) + .forEach(System.out::println); } - public static List getLowCaloricDishesNamesInJava7(List dishes){ - List lowCaloricDishes = new ArrayList<>(); - for(Dish d: dishes){ - if(d.getCalories() < 400){ + public static List getLowCaloricDishesNamesInJava7(List dishes) { + List lowCaloricDishes = new ArrayList<>(dishes.size()); + // for-each + for (Dish d : dishes) { + if (d.getCalories() < 400) { lowCaloricDishes.add(d); } } - List lowCaloricDishesName = new ArrayList<>(); + List lowCaloricDishesName = new ArrayList<>(lowCaloricDishes.size()); + // lowCaloricDishes.sort((d1, d2) -> Integer.compare(d1.getCalories(), d2.getCalories())) Collections.sort(lowCaloricDishes, new Comparator() { - public int compare(Dish d1, Dish d2){ + public int compare(Dish d1, Dish d2) { return Integer.compare(d1.getCalories(), d2.getCalories()); } }); - for(Dish d: lowCaloricDishes){ + for (Dish d : lowCaloricDishes) { lowCaloricDishesName.add(d.getName()); } return lowCaloricDishesName; } - public static List getLowCaloricDishesNamesInJava8(List dishes){ + public static List getLowCaloricDishesNamesInJava8(List dishes) { return dishes.stream() .filter(d -> d.getCalories() < 400) - .sorted(comparing(Dish::getCalories)) + .sorted(Comparator.comparing(Dish::getCalories)) .map(Dish::getName) - .collect(toList()); + .collect(Collectors.toList()); } } diff --git a/src/main/java/lambdasinaction/chap4/StreamVsCollection.java b/src/main/java/lambdasinaction/chap4/StreamVsCollection.java index a72a0730..4f7e67bb 100644 --- a/src/main/java/lambdasinaction/chap4/StreamVsCollection.java +++ b/src/main/java/lambdasinaction/chap4/StreamVsCollection.java @@ -2,17 +2,17 @@ import java.util.*; import java.util.stream.*; -import static java.util.stream.Collectors.toList; - public class StreamVsCollection { - public static void main(String...args){ + public static void main(String... args) { List names = Arrays.asList("Java8", "Lambdas", "In", "Action"); + // Performs an action for each element of this stream. Stream s = names.stream(); s.forEach(System.out::println); // uncommenting this line will result in an IllegalStateException // because streams can be consumed only once + // 数据流只能被消费一次 //s.forEach(System.out::println); } -} \ No newline at end of file +} diff --git a/src/main/java/lambdasinaction/chap5/BuildingStreams.java b/src/main/java/lambdasinaction/chap5/BuildingStreams.java index 15280a39..575ee2e8 100644 --- a/src/main/java/lambdasinaction/chap5/BuildingStreams.java +++ b/src/main/java/lambdasinaction/chap5/BuildingStreams.java @@ -6,13 +6,17 @@ import java.nio.charset.Charset; import java.nio.file.*; +/** + * Chapter 5: Processing data with streams / 处理数据流 + */ public class BuildingStreams { - public static void main(String...args) throws Exception{ - + public static void main(String... args) throws Exception { + // 数据流 // Stream.of Stream stream = Stream.of("Java 8", "Lambdas", "In", "Action"); - stream.map(String::toUpperCase).forEach(System.out::println); + stream.map(String::toUpperCase) + .forEach(System.out::println); // Stream.empty Stream emptyStream = Stream.empty(); @@ -23,56 +27,58 @@ public static void main(String...args) throws Exception{ // Stream.iterate Stream.iterate(0, n -> n + 2) - .limit(10) - .forEach(System.out::println); + .limit(10) + .forEach(System.out::println); - // fibonnaci with iterate - Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1],t[0] + t[1]}) - .limit(10) - .forEach(t -> System.out.println("(" + t[0] + ", " + t[1] + ")")); - - Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1],t[0] + t[1]}) - .limit(10) - . map(t -> t[0]) - .forEach(System.out::println); + // Fibonacci Sequence with iterate + Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]}) + .limit(10) + .forEach(t -> System.out.println("(" + t[0] + ", " + t[1] + ")")); + + Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1], t[0] + t[1]}) + .limit(10) + .map(t -> t[0]) + .forEach(System.out::println); // random stream of doubles with Stream.generate Stream.generate(Math::random) - .limit(10) - .forEach(System.out::println); - + .limit(10) + .forEach(System.out::println); + // stream of 1s with Stream.generate IntStream.generate(() -> 1) - .limit(5) - .forEach(System.out::println); + .limit(5) + .forEach(System.out::println); - IntStream.generate(new IntSupplier(){ - public int getAsInt(){ - return 2; - } - }).limit(5) - .forEach(System.out::println); - + IntStream.generate( + new IntSupplier() { + public int getAsInt() { + return 2; + } + }) + .limit(5) + .forEach(System.out::println); - IntSupplier fib = new IntSupplier(){ - private int previous = 0; - private int current = 1; - public int getAsInt(){ - int nextValue = this.previous + this.current; - this.previous = this.current; - this.current = nextValue; - return this.previous; - } - }; - IntStream.generate(fib).limit(10).forEach(System.out::println); - long uniqueWords = Files.lines(Paths.get("lambdasinaction/chap5/data.txt"), Charset.defaultCharset()) - .flatMap(line -> Arrays.stream(line.split(" "))) - .distinct() - .count(); - - System.out.println("There are " + uniqueWords + " unique words in data.txt"); + IntSupplier fib = new IntSupplier() { + private int previous = 0; + private int current = 1; + public int getAsInt() { + int nextValue = this.previous + this.current; + this.previous = this.current; + this.current = nextValue; + return this.previous; + } + }; + IntStream.generate(fib) + .limit(10) + .forEach(System.out::println); + long uniqueWords = Files.lines(Paths.get("lambdasinaction/chap5/data.txt"), Charset.defaultCharset()) + .flatMap(line -> Arrays.stream(line.split(" "))) + .distinct() + .count(); + System.out.println("There are " + uniqueWords + " unique words in data.txt"); } } diff --git a/src/main/java/lambdasinaction/chap5/Filtering.java b/src/main/java/lambdasinaction/chap5/Filtering.java index 066c8242..6a1e823a 100644 --- a/src/main/java/lambdasinaction/chap5/Filtering.java +++ b/src/main/java/lambdasinaction/chap5/Filtering.java @@ -1,47 +1,46 @@ package lambdasinaction.chap5; + import lambdasinaction.chap4.*; -import java.util.stream.*; import java.util.*; -import static java.util.stream.Collectors.toList; - -import static lambdasinaction.chap4.Dish.menu; +import java.util.stream.Collectors; -public class Filtering{ +/** + * 过滤操作 + */ +public class Filtering { - public static void main(String...args){ + public static void main(String... args) { + // 实例方法引用函数对象 // Filtering with predicate List vegetarianMenu = - menu.stream() - .filter(Dish::isVegetarian) - .collect(toList()); - + Dish.menu.stream() + .filter(Dish::isVegetarian) + .collect(Collectors.toList()); vegetarianMenu.forEach(System.out::println); // Filtering unique elements List numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); numbers.stream() - .filter(i -> i % 2 == 0) - .distinct() - .forEach(System.out::println); + .filter(i -> i % 2 == 0) + .distinct() + .forEach(System.out::println); // Truncating a stream List dishesLimit3 = - menu.stream() - .filter(d -> d.getCalories() > 300) - .limit(3) - .collect(toList()); - + Dish.menu.stream() + .filter(d -> d.getCalories() > 300) + .limit(3) + .collect(Collectors.toList()); dishesLimit3.forEach(System.out::println); // Skipping elements List dishesSkip2 = - menu.stream() - .filter(d -> d.getCalories() > 300) - .skip(2) - .collect(toList()); - + Dish.menu.stream() + .filter(d -> d.getCalories() > 300) + .skip(2) + .collect(Collectors.toList()); dishesSkip2.forEach(System.out::println); } } diff --git a/src/main/java/lambdasinaction/chap5/Finding.java b/src/main/java/lambdasinaction/chap5/Finding.java index acccc543..cd5b0b39 100644 --- a/src/main/java/lambdasinaction/chap5/Finding.java +++ b/src/main/java/lambdasinaction/chap5/Finding.java @@ -1,39 +1,44 @@ package lambdasinaction.chap5; + import lambdasinaction.chap4.*; -import java.util.stream.*; import java.util.*; -import static lambdasinaction.chap4.Dish.menu; - -public class Finding{ +/** + * 查找操作 + */ +public class Finding { - public static void main(String...args){ - if(isVegetarianFriendlyMenu()){ + public static void main(String... args) { + if (isVegetarianFriendlyMenu()) { System.out.println("Vegetarian friendly"); } System.out.println(isHealthyMenu()); System.out.println(isHealthyMenu2()); - + Optional dish = findVegetarianDish(); dish.ifPresent(d -> System.out.println(d.getName())); } - - private static boolean isVegetarianFriendlyMenu(){ - return menu.stream().anyMatch(Dish::isVegetarian); + + private static boolean isVegetarianFriendlyMenu() { + return Dish.menu.stream() + .anyMatch(Dish::isVegetarian); } - - private static boolean isHealthyMenu(){ - return menu.stream().allMatch(d -> d.getCalories() < 1000); + + private static boolean isHealthyMenu() { + return Dish.menu.stream() + .allMatch(d -> d.getCalories() < 1000); } - - private static boolean isHealthyMenu2(){ - return menu.stream().noneMatch(d -> d.getCalories() >= 1000); + + private static boolean isHealthyMenu2() { + return Dish.menu.stream() + .noneMatch(d -> d.getCalories() >= 1000); } - - private static Optional findVegetarianDish(){ - return menu.stream().filter(Dish::isVegetarian).findAny(); + + private static Optional findVegetarianDish() { + return Dish.menu.stream() + .filter(Dish::isVegetarian) + .findAny(); } - } diff --git a/src/main/java/lambdasinaction/chap5/Laziness.java b/src/main/java/lambdasinaction/chap5/Laziness.java index a3df328a..fb9dada2 100644 --- a/src/main/java/lambdasinaction/chap5/Laziness.java +++ b/src/main/java/lambdasinaction/chap5/Laziness.java @@ -2,8 +2,7 @@ import java.util.Arrays; import java.util.List; - -import static java.util.stream.Collectors.toList; +import java.util.stream.Collectors; /** * Created by raoul-gabrielurma on 14/01/2014. @@ -14,17 +13,15 @@ public static void main(String[] args) { List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8); List twoEvenSquares = numbers.stream() - .filter(n -> { - System.out.println("filtering " + n); return n % 2 == 0; - }) - .map(n -> { - System.out.println("mapping " + n); - return n * n; - }) - .limit(2) - .collect(toList()); - + .filter(n -> { + System.out.println("filtering " + n); + return n % 2 == 0; + }) + .map(n -> { + System.out.println("mapping " + n); + return n * n; + }) + .limit(2) + .collect(Collectors.toList()); } - - } diff --git a/src/main/java/lambdasinaction/chap5/Mapping.java b/src/main/java/lambdasinaction/chap5/Mapping.java index 7bf4caba..83fd7b41 100644 --- a/src/main/java/lambdasinaction/chap5/Mapping.java +++ b/src/main/java/lambdasinaction/chap5/Mapping.java @@ -3,42 +3,44 @@ import lambdasinaction.chap4.*; import java.util.*; -import static java.util.stream.Collectors.toList; -import static lambdasinaction.chap4.Dish.menu; +import java.util.stream.Collectors; -public class Mapping{ +/** + * 类型映射,类型转换系统 + */ +public class Mapping { - public static void main(String...args){ + public static void main(String... args) { // map - List dishNames = menu.stream() - .map(Dish::getName) - .collect(toList()); + List dishNames = Dish.menu.stream() + .map(Dish::getName) + .collect(Collectors.toList()); System.out.println(dishNames); // map List words = Arrays.asList("Hello", "World"); List wordLengths = words.stream() - .map(String::length) - .collect(toList()); + .map(String::length) + .collect(Collectors.toList()); System.out.println(wordLengths); // flatMap words.stream() - .flatMap((String line) -> Arrays.stream(line.split(""))) - .distinct() - .forEach(System.out::println); + .flatMap((String line) -> Arrays.stream(line.split(""))) + .distinct() + .forEach(System.out::println); // flatMap - List numbers1 = Arrays.asList(1,2,3,4,5); - List numbers2 = Arrays.asList(6,7,8); + List numbers1 = Arrays.asList(1, 2, 3, 4, 5); + List numbers2 = Arrays.asList(6, 7, 8); List pairs = - numbers1.stream() - .flatMap((Integer i) -> numbers2.stream() - .map((Integer j) -> new int[]{i, j}) - ) - .filter(pair -> (pair[0] + pair[1]) % 3 == 0) - .collect(toList()); + numbers1.stream() + .flatMap((Integer i) -> numbers2.stream() + .map((Integer j) -> new int[]{i, j}) + ) + .filter(pair -> (pair[0] + pair[1]) % 3 == 0) + .collect(Collectors.toList()); pairs.forEach(pair -> System.out.println("(" + pair[0] + ", " + pair[1] + ")")); } } diff --git a/src/main/java/lambdasinaction/chap5/NumericStreams.java b/src/main/java/lambdasinaction/chap5/NumericStreams.java index e5f8cca8..7a7bfe96 100644 --- a/src/main/java/lambdasinaction/chap5/NumericStreams.java +++ b/src/main/java/lambdasinaction/chap5/NumericStreams.java @@ -1,34 +1,35 @@ package lambdasinaction.chap5; + import lambdasinaction.chap4.*; import java.util.stream.*; import java.util.*; -import static lambdasinaction.chap4.Dish.menu; +/** + * 数字流 + */ +public class NumericStreams { -public class NumericStreams{ + public static void main(String... args) { - public static void main(String...args){ - - List numbers = Arrays.asList(3,4,5,1,2); + List numbers = Arrays.asList(3, 4, 5, 1, 2); + Arrays.stream(numbers.toArray()) + .forEach(System.out::println); - Arrays.stream(numbers.toArray()).forEach(System.out::println); - int calories = menu.stream() - .mapToInt(Dish::getCalories) - .sum(); + int calories = Dish.menu.stream() + .mapToInt(Dish::getCalories) + .sum(); System.out.println("Number of calories:" + calories); - // max and OptionalInt - OptionalInt maxCalories = menu.stream() - .mapToInt(Dish::getCalories) - .max(); + OptionalInt maxCalories = Dish.menu.stream() + .mapToInt(Dish::getCalories) + .max(); int max; - if(maxCalories.isPresent()){ + if (maxCalories.isPresent()) { max = maxCalories.getAsInt(); - } - else { + } else { // we can choose a default value max = 1; } @@ -36,21 +37,19 @@ public static void main(String...args){ // numeric ranges IntStream evenNumbers = IntStream.rangeClosed(1, 100) - .filter(n -> n % 2 == 0); - + .filter(n -> n % 2 == 0); System.out.println(evenNumbers.count()); Stream pythagoreanTriples = - IntStream.rangeClosed(1, 100).boxed() + IntStream.rangeClosed(1, 100).boxed() .flatMap(a -> IntStream.rangeClosed(a, 100) - .filter(b -> Math.sqrt(a*a + b*b) % 1 == 0).boxed() - .map(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)})); - - pythagoreanTriples.forEach(t -> System.out.println(t[0] + ", " + t[1] + ", " + t[2])); - + .filter(b -> Math.sqrt(a * a + b * b) % 1 == 0) + .boxed() + .map(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)})); + pythagoreanTriples.forEach(t -> System.out.println(t[0] + ", " + t[1] + ", " + t[2])); } - - public static boolean isPerfectSquare(int n){ + + public static boolean isPerfectSquare(int n) { return Math.sqrt(n) % 1 == 0; } diff --git a/src/main/java/lambdasinaction/chap5/PuttingIntoPractice.java b/src/main/java/lambdasinaction/chap5/PuttingIntoPractice.java index d0b13ae5..810a9627 100644 --- a/src/main/java/lambdasinaction/chap5/PuttingIntoPractice.java +++ b/src/main/java/lambdasinaction/chap5/PuttingIntoPractice.java @@ -1,90 +1,92 @@ package lambdasinaction.chap5; -import lambdasinaction.chap5.*; - import java.util.*; +import java.util.stream.Collectors; -import static java.util.Comparator.comparing; -import static java.util.stream.Collectors.toList; +/** + * 数据流操作实践 + */ +public class PuttingIntoPractice { -public class PuttingIntoPractice{ - public static void main(String ...args){ + public static void main(String... args) { Trader raoul = new Trader("Raoul", "Cambridge"); - Trader mario = new Trader("Mario","Milan"); - Trader alan = new Trader("Alan","Cambridge"); - Trader brian = new Trader("Brian","Cambridge"); - - List transactions = Arrays.asList( - new Transaction(brian, 2011, 300), - new Transaction(raoul, 2012, 1000), - new Transaction(raoul, 2011, 400), - new Transaction(mario, 2012, 710), - new Transaction(mario, 2012, 700), - new Transaction(alan, 2012, 950) - ); - - + Trader mario = new Trader("Mario", "Milan"); + Trader alan = new Trader("Alan", "Cambridge"); + Trader brian = new Trader("Brian", "Cambridge"); + + List transactions = Arrays.asList( + new Transaction(brian, 2011, 300), + new Transaction(raoul, 2012, 1000), + new Transaction(raoul, 2011, 400), + new Transaction(mario, 2012, 710), + new Transaction(mario, 2012, 700), + new Transaction(alan, 2012, 950) + ); + + // Query 1: Find all transactions from year 2011 and sort them by value (small to high). + // 排序 List tr2011 = transactions.stream() - .filter(transaction -> transaction.getYear() == 2011) - .sorted(comparing(Transaction::getValue)) - .collect(toList()); + .filter(transaction -> transaction.getYear() == 2011) + .sorted(Comparator.comparing(Transaction::getValue)) + .collect(Collectors.toList()); System.out.println(tr2011); - + + // Query 2: What are all the unique cities where the traders work? - List cities = - transactions.stream() - .map(transaction -> transaction.getTrader().getCity()) - .distinct() - .collect(toList()); + // 唯一约束 + List cities = transactions.stream() + .map(transaction -> transaction.getTrader().getCity()) + .distinct() + .collect(Collectors.toList()); System.out.println(cities); + // Query 3: Find all traders from Cambridge and sort them by name. - - List traders = - transactions.stream() - .map(Transaction::getTrader) - .filter(trader -> trader.getCity().equals("Cambridge")) - .distinct() - .sorted(comparing(Trader::getName)) - .collect(toList()); + // 唯一约束+排序 + List traders = transactions.stream() + .map(Transaction::getTrader) + .filter(trader -> trader.getCity().equals("Cambridge")) + .distinct() + .sorted(Comparator.comparing(Trader::getName)) + .collect(Collectors.toList()); System.out.println(traders); - - + + // Query 4: Return a string of all traders’ names sorted alphabetically. - - String traderStr = - transactions.stream() - .map(transaction -> transaction.getTrader().getName()) - .distinct() - .sorted() - .reduce("", (n1, n2) -> n1 + n2); + // 映射-规约 + String traderStr = transactions.stream() + .map(transaction -> transaction.getTrader().getName()) + .distinct() + .sorted() + .reduce("", (n1, n2) -> n1 + n2); System.out.println(traderStr); - + + // Query 5: Are there any trader based in Milan? - - boolean milanBased = - transactions.stream() - .anyMatch(transaction -> transaction.getTrader() - .getCity() - .equals("Milan") - ); + // 匹配 + boolean milanBased = transactions.stream() + .anyMatch(transaction -> transaction.getTrader() + .getCity() + .equals("Milan") + ); System.out.println(milanBased); - - + + // Query 6: Update all transactions so that the traders from Milan are set to Cambridge. + // 遍历 transactions.stream() - .map(Transaction::getTrader) - .filter(trader -> trader.getCity().equals("Milan")) - .forEach(trader -> trader.setCity("Cambridge")); + .map(Transaction::getTrader) + .filter(trader -> trader.getCity().equals("Milan")) + .forEach(trader -> trader.setCity("Cambridge")); System.out.println(transactions); - - + + // Query 7: What's the highest value in all the transactions? - int highestValue = - transactions.stream() - .map(Transaction::getValue) - .reduce(0, Integer::max); - System.out.println(highestValue); + // 映射-规约 + int highestValue = transactions.stream() + .map(Transaction::getValue) + .reduce(0, Integer::max); + System.out.println(highestValue); } -} \ No newline at end of file +} diff --git a/src/main/java/lambdasinaction/chap5/Reducing.java b/src/main/java/lambdasinaction/chap5/Reducing.java index 93aed73e..78dfe039 100644 --- a/src/main/java/lambdasinaction/chap5/Reducing.java +++ b/src/main/java/lambdasinaction/chap5/Reducing.java @@ -1,31 +1,36 @@ package lambdasinaction.chap5; + import lambdasinaction.chap4.*; -import java.util.stream.*; import java.util.*; -import static lambdasinaction.chap4.Dish.menu; - -public class Reducing{ +/** + * 拆分-规约,分而治之思想 + */ +public class Reducing { - public static void main(String...args){ + public static void main(String... args) { - List numbers = Arrays.asList(3,4,5,1,2); - int sum = numbers.stream().reduce(0, (a, b) -> a + b); + List numbers = Arrays.asList(3, 4, 5, 1, 2); + int sum = numbers.stream() + .reduce(0, (a, b) -> a + b); System.out.println(sum); - int sum2 = numbers.stream().reduce(0, Integer::sum); + int sum2 = numbers.stream() + .reduce(0, Integer::sum); System.out.println(sum2); - int max = numbers.stream().reduce(0, (a, b) -> Integer.max(a, b)); + int max = numbers.stream() + .reduce(0, (a, b) -> Integer.max(a, b)); System.out.println(max); - Optional min = numbers.stream().reduce(Integer::min); + Optional min = numbers.stream() + .reduce(Integer::min); min.ifPresent(System.out::println); - int calories = menu.stream() - .map(Dish::getCalories) - .reduce(0, Integer::sum); + int calories = Dish.menu.stream() + .map(Dish::getCalories) + .reduce(0, Integer::sum); System.out.println("Number of calories:" + calories); } } diff --git a/src/main/java/lambdasinaction/chap5/Trader.java b/src/main/java/lambdasinaction/chap5/Trader.java index 7487a8c6..8070852d 100644 --- a/src/main/java/lambdasinaction/chap5/Trader.java +++ b/src/main/java/lambdasinaction/chap5/Trader.java @@ -1,27 +1,29 @@ package lambdasinaction.chap5; -public class Trader{ - - private String name; - private String city; - public Trader(String n, String c){ - this.name = n; - this.city = c; - } +public class Trader { - public String getName(){ - return this.name; - } + private final String name; + private String city; - public String getCity(){ - return this.city; - } + public Trader(String n, String c) { + this.name = n; + this.city = c; + } - public void setCity(String newCity){ - this.city = newCity; - } + public String getName() { + return this.name; + } - public String toString(){ - return "Trader:"+this.name + " in " + this.city; - } -} \ No newline at end of file + public String getCity() { + return this.city; + } + + public void setCity(String newCity) { + this.city = newCity; + } + + @Override + public String toString() { + return "Trader:" + this.name + " in " + this.city; + } +} diff --git a/src/main/java/lambdasinaction/chap5/Transaction.java b/src/main/java/lambdasinaction/chap5/Transaction.java index 754e3839..7b188ec8 100644 --- a/src/main/java/lambdasinaction/chap5/Transaction.java +++ b/src/main/java/lambdasinaction/chap5/Transaction.java @@ -1,33 +1,33 @@ package lambdasinaction.chap5; -public class Transaction{ +public class Transaction { - private Trader trader; - private int year; - private int value; + private final Trader trader; + private final int year; + private final int value; - public Transaction(Trader trader, int year, int value) - { - this.trader = trader; - this.year = year; - this.value = value; - } + public Transaction(Trader trader, int year, int value) { + this.trader = trader; + this.year = year; + this.value = value; + } - public Trader getTrader(){ - return this.trader; - } + public Trader getTrader() { + return this.trader; + } - public int getYear(){ - return this.year; - } + public int getYear() { + return this.year; + } - public int getValue(){ - return this.value; - } - - public String toString(){ - return "{" + this.trader + ", " + - "year: "+this.year+", " + - "value:" + this.value +"}"; - } -} \ No newline at end of file + public int getValue() { + return this.value; + } + + @Override + public String toString() { + return "{" + this.trader + ", " + + "year: " + this.year + ", " + + "value:" + this.value + "}"; + } +}