forked from java8/Java8InAction
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Technical proofing by Jean-Francois Morin
- Loading branch information
Showing
12 changed files
with
323 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package lambdasinaction.appa; | ||
|
||
import java.lang.annotation.Repeatable; | ||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
|
||
@Repeatable(Authors.class) | ||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface Author { | ||
|
||
String name(); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package lambdasinaction.appa; | ||
|
||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
|
||
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface Authors { | ||
|
||
Author[] value(); | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package lambdasinaction.appa; | ||
|
||
import java.util.Arrays; | ||
|
||
@Author(name = "Raoul") | ||
@Author(name = "Mario") | ||
@Author(name = "Alan") | ||
public class Book { | ||
|
||
public static void main(String[] args) { | ||
Author[] authors = Book.class.getAnnotationsByType(Author.class); | ||
Arrays.asList(authors).stream().forEach(a -> { | ||
System.out.println(a.name()); | ||
}); | ||
} | ||
|
||
} |
2 changes: 1 addition & 1 deletion
2
...a/lambdasinaction/chap6/StreamForker.java → ...va/lambdasinaction/appc/StreamForker.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package lambdasinaction.chap6; | ||
package lambdasinaction.appc; | ||
|
||
import java.util.*; | ||
import java.util.concurrent.*; | ||
|
2 changes: 1 addition & 1 deletion
2
...asinaction/chap6/StreamForkerExample.java → ...dasinaction/appc/StreamForkerExample.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package lambdasinaction.chap6; | ||
package lambdasinaction.appc; | ||
|
||
import lambdasinaction.chap5.*; | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package lambdasinaction.appd; | ||
|
||
import java.util.function.Function; | ||
|
||
public class InnerClass { | ||
Function<Object, String> f = new Function<Object, String>() { | ||
@Override | ||
public String apply(Object obj) { | ||
return obj.toString(); | ||
} | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
package lambdasinaction.appd; | ||
|
||
import java.util.function.Function; | ||
|
||
public class Lambda { | ||
Function<Object, String> f = obj -> obj.toString(); | ||
} |
163 changes: 163 additions & 0 deletions
163
src/main/java/lambdasinaction/chap10/v1/BestPriceFinder.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
package lambdasinaction.chap10.v1; | ||
|
||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.List; | ||
import java.util.concurrent.Callable; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.Executor; | ||
import java.util.concurrent.ExecutorService; | ||
import java.util.concurrent.Executors; | ||
import java.util.concurrent.Future; | ||
import java.util.concurrent.ThreadFactory; | ||
import java.util.stream.Collectors; | ||
import java.util.stream.Stream; | ||
|
||
import lambdasinaction.chap10.ExchangeService; | ||
import lambdasinaction.chap10.ExchangeService.Money; | ||
|
||
public class BestPriceFinder { | ||
|
||
private final List<Shop> shops = Arrays.asList(new Shop("BestPrice"), | ||
new Shop("LetsSaveBig"), | ||
new Shop("MyFavoriteShop"), | ||
new Shop("BuyItAll")/*, | ||
new Shop("ShopEasy")*/); | ||
|
||
private final Executor executor = Executors.newFixedThreadPool(shops.size(), new ThreadFactory() { | ||
@Override | ||
public Thread newThread(Runnable r) { | ||
Thread t = new Thread(r); | ||
t.setDaemon(true); | ||
return t; | ||
} | ||
}); | ||
|
||
public List<String> findPricesSequential(String product) { | ||
return shops.stream() | ||
.map(shop -> shop.getName() + " price is " + shop.getPrice(product)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public List<String> findPricesParallel(String product) { | ||
return shops.parallelStream() | ||
.map(shop -> shop.getName() + " price is " + shop.getPrice(product)) | ||
.collect(Collectors.toList()); | ||
} | ||
|
||
public List<String> findPricesFuture(String product) { | ||
List<CompletableFuture<String>> priceFutures = | ||
shops.stream() | ||
.map(shop -> CompletableFuture.supplyAsync(() -> shop.getName() + " price is " | ||
+ shop.getPrice(product), executor)) | ||
.collect(Collectors.toList()); | ||
|
||
List<String> prices = priceFutures.stream() | ||
.map(CompletableFuture::join) | ||
.collect(Collectors.toList()); | ||
return prices; | ||
} | ||
|
||
public List<String> findPricesInUSD(String product) { | ||
List<CompletableFuture<Double>> priceFutures = new ArrayList<>(); | ||
for (Shop shop : shops) { | ||
// Start of Listing 10.20. | ||
// Only the type of futurePriceInUSD has been changed to | ||
// CompletableFuture so that it is compatible with the | ||
// CompletableFuture::join operation below. | ||
CompletableFuture<Double> futurePriceInUSD = | ||
CompletableFuture.supplyAsync(() -> shop.getPrice(product)) | ||
.thenCombine( | ||
CompletableFuture.supplyAsync( | ||
() -> ExchangeService.getRate(Money.EUR, Money.USD)), | ||
(price, rate) -> price * rate | ||
); | ||
priceFutures.add(futurePriceInUSD); | ||
} | ||
// Drawback: The shop is not accessible anymore outside the loop, | ||
// so the getName() call below has been commented out. | ||
List<String> prices = priceFutures | ||
.stream() | ||
.map(CompletableFuture::join) | ||
.map(price -> /*shop.getName() +*/ " price is " + price) | ||
.collect(Collectors.toList()); | ||
return prices; | ||
} | ||
|
||
public List<String> findPricesInUSDJava7(String product) { | ||
ExecutorService executor = Executors.newCachedThreadPool(); | ||
List<Future<Double>> priceFutures = new ArrayList<>(); | ||
for (Shop shop : shops) { | ||
final Future<Double> futureRate = executor.submit(new Callable<Double>() { | ||
public Double call() { | ||
return ExchangeService.getRate(Money.EUR, Money.USD); | ||
} | ||
}); | ||
Future<Double> futurePriceInUSD = executor.submit(new Callable<Double>() { | ||
public Double call() { | ||
try { | ||
double priceInEUR = shop.getPrice(product); | ||
return priceInEUR * futureRate.get(); | ||
} catch (InterruptedException | ExecutionException e) { | ||
throw new RuntimeException(e.getMessage(), e); | ||
} | ||
} | ||
}); | ||
priceFutures.add(futurePriceInUSD); | ||
} | ||
List<String> prices = new ArrayList<>(); | ||
for (Future<Double> priceFuture : priceFutures) { | ||
try { | ||
prices.add(/*shop.getName() +*/ " price is " + priceFuture.get()); | ||
} | ||
catch (ExecutionException | InterruptedException e) { | ||
e.printStackTrace(); | ||
} | ||
} | ||
return prices; | ||
} | ||
|
||
public List<String> findPricesInUSD2(String product) { | ||
List<CompletableFuture<String>> priceFutures = new ArrayList<>(); | ||
for (Shop shop : shops) { | ||
// Here, an extra operation has been added so that the shop name | ||
// is retrieved within the loop. As a result, we now deal with | ||
// CompletableFuture<String> instances. | ||
CompletableFuture<String> futurePriceInUSD = | ||
CompletableFuture.supplyAsync(() -> shop.getPrice(product)) | ||
.thenCombine( | ||
CompletableFuture.supplyAsync( | ||
() -> ExchangeService.getRate(Money.EUR, Money.USD)), | ||
(price, rate) -> price * rate | ||
).thenApply(price -> shop.getName() + " price is " + price); | ||
priceFutures.add(futurePriceInUSD); | ||
} | ||
List<String> prices = priceFutures | ||
.stream() | ||
.map(CompletableFuture::join) | ||
.collect(Collectors.toList()); | ||
return prices; | ||
} | ||
|
||
public List<String> findPricesInUSD3(String product) { | ||
// Here, the for loop has been replaced by a mapping function... | ||
Stream<CompletableFuture<String>> priceFuturesStream = shops | ||
.stream() | ||
.map(shop -> CompletableFuture | ||
.supplyAsync(() -> shop.getPrice(product)) | ||
.thenCombine( | ||
CompletableFuture.supplyAsync(() -> ExchangeService.getRate(Money.EUR, Money.USD)), | ||
(price, rate) -> price * rate) | ||
.thenApply(price -> shop.getName() + " price is " + price)); | ||
// However, we should gather the CompletableFutures into a List so that the asynchronous | ||
// operations are triggered before being "joined." | ||
List<CompletableFuture<String>> priceFutures = priceFuturesStream.collect(Collectors.toList()); | ||
List<String> prices = priceFutures | ||
.stream() | ||
.map(CompletableFuture::join) | ||
.collect(Collectors.toList()); | ||
return prices; | ||
} | ||
|
||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/lambdasinaction/chap10/v1/BestPriceFinderMain.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package lambdasinaction.chap10.v1; | ||
|
||
import java.util.List; | ||
import java.util.function.Supplier; | ||
|
||
public class BestPriceFinderMain { | ||
|
||
private static BestPriceFinder bestPriceFinder = new BestPriceFinder(); | ||
|
||
public static void main(String[] args) { | ||
execute("sequential", () -> bestPriceFinder.findPricesSequential("myPhone27S")); | ||
execute("parallel", () -> bestPriceFinder.findPricesParallel("myPhone27S")); | ||
execute("composed CompletableFuture", () -> bestPriceFinder.findPricesFuture("myPhone27S")); | ||
execute("combined USD CompletableFuture", () -> bestPriceFinder.findPricesInUSD("myPhone27S")); | ||
execute("combined USD CompletableFuture v2", () -> bestPriceFinder.findPricesInUSD2("myPhone27S")); | ||
execute("combined USD CompletableFuture v3", () -> bestPriceFinder.findPricesInUSD3("myPhone27S")); | ||
} | ||
|
||
private static void execute(String msg, Supplier<List<String>> s) { | ||
long start = System.nanoTime(); | ||
System.out.println(s.get()); | ||
long duration = (System.nanoTime() - start) / 1_000_000; | ||
System.out.println(msg + " done in " + duration + " msecs"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package lambdasinaction.chap10.v1; | ||
|
||
import static lambdasinaction.chap10.Util.delay; | ||
|
||
import java.util.Random; | ||
import java.util.concurrent.CompletableFuture; | ||
import java.util.concurrent.Future; | ||
|
||
public class Shop { | ||
|
||
private final String name; | ||
private final Random random; | ||
|
||
public Shop(String name) { | ||
this.name = name; | ||
random = new Random(name.charAt(0) * name.charAt(1) * name.charAt(2)); | ||
} | ||
|
||
public double getPrice(String product) { | ||
return calculatePrice(product); | ||
} | ||
|
||
private double calculatePrice(String product) { | ||
delay(); | ||
return random.nextDouble() * product.charAt(0) + product.charAt(1); | ||
} | ||
|
||
public Future<Double> getPriceAsync(String product) { | ||
CompletableFuture<Double> futurePrice = new CompletableFuture<>(); | ||
new Thread( () -> { | ||
double price = calculatePrice(product); | ||
futurePrice.complete(price); | ||
}).start(); | ||
return futurePrice; | ||
} | ||
|
||
public String getName() { | ||
return name; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package lambdasinaction.chap10.v1; | ||
|
||
import java.util.concurrent.ExecutionException; | ||
import java.util.concurrent.Future; | ||
|
||
public class ShopMain { | ||
|
||
public static void main(String[] args) { | ||
Shop shop = new Shop("BestShop"); | ||
long start = System.nanoTime(); | ||
Future<Double> futurePrice = shop.getPriceAsync("my favorite product"); | ||
long invocationTime = ((System.nanoTime() - start) / 1_000_000); | ||
System.out.println("Invocation returned after " + invocationTime | ||
+ " msecs"); | ||
// Do some more tasks, like querying other shops | ||
doSomethingElse(); | ||
// while the price of the product is being calculated | ||
try { | ||
double price = futurePrice.get(); | ||
System.out.printf("Price is %.2f%n", price); | ||
} catch (ExecutionException | InterruptedException e) { | ||
throw new RuntimeException(e); | ||
} | ||
long retrievalTime = ((System.nanoTime() - start) / 1_000_000); | ||
System.out.println("Price returned after " + retrievalTime + " msecs"); | ||
} | ||
|
||
private static void doSomethingElse() { | ||
System.out.println("Doing something else..."); | ||
} | ||
|
||
} |
32 changes: 0 additions & 32 deletions
32
src/main/java/lambdasinaction/chap13/PersistentDataStructures.java
This file was deleted.
Oops, something went wrong.