From df8e05f771d61338255b4ebe7fe0f95928727e10 Mon Sep 17 00:00:00 2001 From: Mario Fusco Date: Wed, 23 Mar 2016 19:21:20 +0100 Subject: [PATCH 1/4] dsl chapter --- .../java/lambdasinaction/dsl/Grouping.java | 79 +++++++++++++++ .../dsl/LambdaOrderBuilder.java | 83 ++++++++++++++++ src/main/java/lambdasinaction/dsl/Main.java | 98 ++++++++++++++++++ .../dsl/MethodChainingOrderBuilder.java | 99 +++++++++++++++++++ src/main/java/lambdasinaction/dsl/Mixed.java | 39 ++++++++ .../lambdasinaction/dsl/MixedBuilder.java | 85 ++++++++++++++++ .../dsl/NestedFunctionOrderBuilder.java | 64 ++++++++++++ .../lambdasinaction/dsl/TaxCalculator.java | 81 +++++++++++++++ .../java/lambdasinaction/dsl/model/Order.java | 43 ++++++++ .../java/lambdasinaction/dsl/model/Stock.java | 40 ++++++++ .../java/lambdasinaction/dsl/model/Tax.java | 31 ++++++ .../java/lambdasinaction/dsl/model/Trade.java | 66 +++++++++++++ 12 files changed, 808 insertions(+) create mode 100644 src/main/java/lambdasinaction/dsl/Grouping.java create mode 100644 src/main/java/lambdasinaction/dsl/LambdaOrderBuilder.java create mode 100644 src/main/java/lambdasinaction/dsl/Main.java create mode 100644 src/main/java/lambdasinaction/dsl/MethodChainingOrderBuilder.java create mode 100644 src/main/java/lambdasinaction/dsl/Mixed.java create mode 100644 src/main/java/lambdasinaction/dsl/MixedBuilder.java create mode 100644 src/main/java/lambdasinaction/dsl/NestedFunctionOrderBuilder.java create mode 100644 src/main/java/lambdasinaction/dsl/TaxCalculator.java create mode 100644 src/main/java/lambdasinaction/dsl/model/Order.java create mode 100644 src/main/java/lambdasinaction/dsl/model/Stock.java create mode 100644 src/main/java/lambdasinaction/dsl/model/Tax.java create mode 100644 src/main/java/lambdasinaction/dsl/model/Trade.java diff --git a/src/main/java/lambdasinaction/dsl/Grouping.java b/src/main/java/lambdasinaction/dsl/Grouping.java new file mode 100644 index 00000000..698764d5 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/Grouping.java @@ -0,0 +1,79 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl; + +import lambdasinaction.chap5.Dish; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collector; + +import static java.util.stream.Collectors.groupingBy; +import static lambdasinaction.chap5.Dish.menu; +import static lambdasinaction.dsl.Grouping.GroupingBuilder.groupOn; + +public class Grouping { + + enum CaloricLevel { DIET, NORMAL, FAT }; + + public static void main(String ... args) { + System.out.println("Dishes grouped by type and caloric level: " + groupDishedByTypeAndCaloricLevel2()); + System.out.println("Dishes grouped by type and caloric level: " + groupDishedByTypeAndCaloricLevel3()); + } + + private static CaloricLevel getCaloricLevel( Dish dish ) { + if (dish.getCalories() <= 400) return CaloricLevel.DIET; + else if (dish.getCalories() <= 700) return CaloricLevel.NORMAL; + else return CaloricLevel.FAT; + } + + private static Map>> groupDishedByTypeAndCaloricLevel2() { + return menu.stream().collect( + twoLevelGroupingBy(Dish::getType, dish -> getCaloricLevel( dish ) ) + ); + } + + public static Collector>>> twoLevelGroupingBy(Function f1, Function f2) { + return groupingBy(f1, groupingBy(f2)); + } + + private static Map>> groupDishedByTypeAndCaloricLevel3() { + Collector>>> c = groupOn( ( Dish dish ) -> getCaloricLevel( dish ) ).after( Dish::getType ).get(); + return menu.stream().collect( c ); + } + + public static class GroupingBuilder { + private final Collector> collector; + + public GroupingBuilder( Collector> collector ) { + this.collector = collector; + } + + public Collector> get() { + return collector; + } + + public GroupingBuilder, J> after(Function classifier) { + return new GroupingBuilder<>( groupingBy( classifier, collector ) ); + } + + public static GroupingBuilder, K> groupOn(Function classifier) { + return new GroupingBuilder<>( groupingBy( classifier ) ); + } + } +} diff --git a/src/main/java/lambdasinaction/dsl/LambdaOrderBuilder.java b/src/main/java/lambdasinaction/dsl/LambdaOrderBuilder.java new file mode 100644 index 00000000..6746c3b1 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/LambdaOrderBuilder.java @@ -0,0 +1,83 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl; + +import lambdasinaction.dsl.model.Order; +import lambdasinaction.dsl.model.Stock; +import lambdasinaction.dsl.model.Trade; + +import java.util.function.Consumer; + +public class LambdaOrderBuilder { + + private Order order = new Order(); + + public static Order order(Consumer consumer) { + LambdaOrderBuilder builder = new LambdaOrderBuilder(); + consumer.accept( builder ); + return builder.order; + } + + public void forCustomer(String customer) { + order.setCustomer( customer ); + } + + public void buy(Consumer consumer) { + trade( consumer, Trade.Type.BUY ); + } + + public void sell(Consumer consumer) { + trade( consumer, Trade.Type.SELL ); + } + + private void trade( Consumer consumer, Trade.Type type ) { + TradeBuilder builder = new TradeBuilder(); + builder.trade.setType( type ); + consumer.accept( builder ); + order.addTrade( builder.trade ); + } + + public static class TradeBuilder { + private Trade trade = new Trade(); + + public void quantity(int quantity) { + trade.setQuantity( quantity ); + } + + public void price(double price) { + trade.setPrice( price ); + } + + public void stock(Consumer consumer) { + StockBuilder builder = new StockBuilder(); + consumer.accept( builder ); + trade.setStock( builder.stock ); + } + } + + public static class StockBuilder { + private Stock stock = new Stock(); + + public void symbol(String symbol) { + stock.setSymbol( symbol ); + } + + public void market(String market) { + stock.setMarket( market ); + } + } +} diff --git a/src/main/java/lambdasinaction/dsl/Main.java b/src/main/java/lambdasinaction/dsl/Main.java new file mode 100644 index 00000000..b50683e5 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/Main.java @@ -0,0 +1,98 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl; + +import lambdasinaction.dsl.model.Order; +import lambdasinaction.dsl.model.Stock; +import lambdasinaction.dsl.model.Trade; + +import static lambdasinaction.dsl.MethodChainingOrderBuilder.forCustomer; +import static lambdasinaction.dsl.NestedFunctionOrderBuilder.*; + +public class Main { + + public void plain() { + Order order = new Order(); + order.setCustomer( "BigBank" ); + + Trade trade1 = new Trade(); + trade1.setType( Trade.Type.BUY ); + + Stock stock1 = new Stock(); + stock1.setSymbol( "IBM" ); + stock1.setMarket( "NYSE" ); + + trade1.setStock( stock1 ); + trade1.setPrice( 125.00 ); + trade1.setQuantity( 80 ); + order.addTrade( trade1 ); + + Trade trade2 = new Trade(); + trade2.setType( Trade.Type.BUY ); + + Stock stock2 = new Stock(); + stock2.setSymbol( "GOOGLE" ); + stock2.setMarket( "NASDAQ" ); + + trade2.setStock( stock2 ); + trade2.setPrice( 375.00 ); + trade2.setQuantity( 50 ); + order.addTrade( trade2 ); + } + + public void methodChaining() { + Order order = forCustomer( "BigBank" ) + .buy( 80 ).stock( "IBM" ).on( "NYSE" ).at( 125.00 ) + .sell( 50 ).stock( "GOOGLE" ).on( "NASDAQ" ).at( 375.00 ) + .end(); + + } + + public void nestedFunction() { + Order order = order("BigBank", + buy(80, + stock( "IBM", on( "NYSE" ) ), + at(125.00)), + sell(50, + stock("GOOGLE", on("NASDAQ")), + at(375.00)) + ); + } + + public void lambda() { + Order order = LambdaOrderBuilder.order( o -> { + o.forCustomer( "BigBank" ); + o.buy( t -> { + t.quantity( 80 ); + t.price( 125.00 ); + t.stock( s -> { + s.symbol( "IBM" ); + s.market( "NYSE" ); + } ); + }); + o.sell( t -> { + t.quantity( 50 ); + t.price( 375.00 ); + t.stock( s -> { + s.symbol( "GOOGLE" ); + s.market( "NASDAQ" ); + } ); + }); + } ); + } + +} diff --git a/src/main/java/lambdasinaction/dsl/MethodChainingOrderBuilder.java b/src/main/java/lambdasinaction/dsl/MethodChainingOrderBuilder.java new file mode 100644 index 00000000..7d771ec5 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/MethodChainingOrderBuilder.java @@ -0,0 +1,99 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl; + +import lambdasinaction.dsl.model.Order; +import lambdasinaction.dsl.model.Stock; +import lambdasinaction.dsl.model.Trade; + +public class MethodChainingOrderBuilder { + + public final Order order = new Order(); + + private MethodChainingOrderBuilder(String customer) { + order.setCustomer( customer ); + } + + public static MethodChainingOrderBuilder forCustomer( String customer ) { + return new MethodChainingOrderBuilder(customer); + } + + public Order end() { + return order; + } + + public TradeBuilder buy(int quantity) { + return new TradeBuilder( this, Trade.Type.BUY, quantity ); + } + + public TradeBuilder sell(int quantity) { + return new TradeBuilder( this, Trade.Type.SELL, quantity ); + } + + private MethodChainingOrderBuilder addTrade(Trade trade) { + order.addTrade( trade ); + return this; + } + + public static class TradeBuilder { + private final MethodChainingOrderBuilder builder; + public final Trade trade = new Trade(); + + private TradeBuilder(MethodChainingOrderBuilder builder, Trade.Type type, int quantity) { + this.builder = builder; + trade.setType( type ); + trade.setQuantity( quantity ); + } + + public StockBuilder stock(String symbol) { + return new StockBuilder( builder, trade, symbol ); + } + } + + public static class TradeBuilderWithStock { + private final MethodChainingOrderBuilder builder; + private final Trade trade; + + public TradeBuilderWithStock( MethodChainingOrderBuilder builder, Trade trade ) { + this.builder = builder; + this.trade = trade; + } + + public MethodChainingOrderBuilder at(double price) { + trade.setPrice( price ); + return builder.addTrade( trade ); + } + } + + public static class StockBuilder { + private final MethodChainingOrderBuilder builder; + private final Trade trade; + private final Stock stock = new Stock(); + + private StockBuilder(MethodChainingOrderBuilder builder, Trade trade, String symbol) { + this.builder = builder; + this.trade = trade; + stock.setSymbol( symbol ); + } + + public TradeBuilderWithStock on(String market) { + stock.setMarket( market ); + trade.setStock( stock ); + return new TradeBuilderWithStock( builder, trade ); + } + } +} diff --git a/src/main/java/lambdasinaction/dsl/Mixed.java b/src/main/java/lambdasinaction/dsl/Mixed.java new file mode 100644 index 00000000..132dd998 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/Mixed.java @@ -0,0 +1,39 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl; + +import lambdasinaction.dsl.model.Order; + +import static lambdasinaction.dsl.MixedBuilder.buy; +import static lambdasinaction.dsl.MixedBuilder.sell; +import static lambdasinaction.dsl.MixedBuilder.forCustomer; + +public class Mixed { + public void mixed() { + Order order = + forCustomer( "BigBank", + buy( t -> t.quantity( 80 ) + .stock( "IBM" ) + .on( "NYSE" ) + .at( 125.00 )), + sell( t -> t.quantity( 50 ) + .stock( "GOOGLE" ) + .on( "NASDAQ" ) + .at( 125.00 )) ); + + } +} diff --git a/src/main/java/lambdasinaction/dsl/MixedBuilder.java b/src/main/java/lambdasinaction/dsl/MixedBuilder.java new file mode 100644 index 00000000..98d7ea97 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/MixedBuilder.java @@ -0,0 +1,85 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl; + +import lambdasinaction.dsl.model.Order; +import lambdasinaction.dsl.model.Stock; +import lambdasinaction.dsl.model.Trade; + +import java.util.function.Consumer; +import java.util.stream.Stream; + +public class MixedBuilder { + + public static Order forCustomer(String customer, TradeBuilder... builders) { + Order order = new Order(); + order.setCustomer( customer ); + Stream.of(builders).forEach( b -> order.addTrade( b.trade ) ); + return order; + } + + public static TradeBuilder buy(Consumer consumer) { + return buildTrade( consumer, Trade.Type.BUY ); + } + + public static TradeBuilder sell(Consumer consumer) { + return buildTrade( consumer, Trade.Type.SELL ); + } + + private static TradeBuilder buildTrade( Consumer consumer, Trade.Type buy ) { + TradeBuilder builder = new TradeBuilder(); + builder.trade.setType( buy ); + consumer.accept( builder ); + return builder; + } + + public static class TradeBuilder { + private Trade trade = new Trade(); + + public TradeBuilder quantity(int quantity) { + trade.setQuantity( quantity ); + return this; + } + + public TradeBuilder at(double price) { + trade.setPrice( price ); + return this; + } + + public StockBuilder stock(String symbol) { + return new StockBuilder(this, trade, symbol); + } + } + + public static class StockBuilder { + private final TradeBuilder builder; + private final Trade trade; + private final Stock stock = new Stock(); + + private StockBuilder(TradeBuilder builder, Trade trade, String symbol) { + this.builder = builder; + this.trade = trade; + stock.setSymbol( symbol ); + } + + public TradeBuilder on(String market) { + stock.setMarket( market ); + trade.setStock( stock ); + return builder; + } + } +} diff --git a/src/main/java/lambdasinaction/dsl/NestedFunctionOrderBuilder.java b/src/main/java/lambdasinaction/dsl/NestedFunctionOrderBuilder.java new file mode 100644 index 00000000..b9daaac9 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/NestedFunctionOrderBuilder.java @@ -0,0 +1,64 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl; + +import lambdasinaction.dsl.model.Order; +import lambdasinaction.dsl.model.Stock; +import lambdasinaction.dsl.model.Trade; + +import java.util.stream.Stream; + +public class NestedFunctionOrderBuilder { + + public static Order order(String customer, Trade... trades) { + Order order = new Order(); + order.setCustomer( customer ); + Stream.of(trades).forEach( order::addTrade ); + return order; + } + + public static Trade buy(int quantity, Stock stock, double price) { + return buildTrade( stock, price, Trade.Type.BUY ); + } + + public static Trade sell(int quantity, Stock stock, double price) { + return buildTrade( stock, price, Trade.Type.SELL ); + } + + private static Trade buildTrade( Stock stock, double price, Trade.Type buy ) { + Trade trade = new Trade(); + trade.setType( buy ); + trade.setStock( stock ); + trade.setPrice( price ); + return trade; + } + + public static double at(double price) { + return price; + } + + public static Stock stock(String symbol, String market) { + Stock stock = new Stock(); + stock.setSymbol( symbol ); + stock.setMarket( market ); + return stock; + } + + public static String on(String market) { + return market; + } +} diff --git a/src/main/java/lambdasinaction/dsl/TaxCalculator.java b/src/main/java/lambdasinaction/dsl/TaxCalculator.java new file mode 100644 index 00000000..9ef38cef --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/TaxCalculator.java @@ -0,0 +1,81 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl; + +import lambdasinaction.dsl.model.Order; +import lambdasinaction.dsl.model.Tax; + +import java.util.function.Function; + +public class TaxCalculator { + + public static double calculate( Order order, boolean useRegional, boolean useGeneral, boolean useSurcharge ) { + double value = order.getValue(); + if (useRegional) value = Tax.regional(value); + if (useGeneral) value = Tax.general(value); + if (useSurcharge) value = Tax.surcharge(value); + return value; + } + + private boolean useRegional; + private boolean useGeneral; + private boolean useSurcharge; + + public TaxCalculator withTaxRegional() { + useRegional = true; + return this; + } + + public TaxCalculator withTaxGeneral() { + useGeneral= true; + return this; + } + + public TaxCalculator withTaxSurcharge() { + useSurcharge = true; + return this; + } + + public double calculate(Order order) { + return calculate( order, useRegional, useGeneral, useSurcharge ); + } + + public Function taxFuncion = Function.identity(); + + public TaxCalculator with(Function f) { + taxFuncion.andThen( f ); + return this; + } + + public double calculateF(Order order) { + return taxFuncion.apply( order.getValue() ); + } + + public static void main(String[] args) { + Order order = new Order(); + + double value = TaxCalculator.calculate( order, true, false, true ); + + value = new TaxCalculator().withTaxRegional() + .withTaxSurcharge() + .calculate( order ); + + value = new TaxCalculator().with(Tax::regional) + .with(Tax::surcharge) + .calculate( order ); + } +} diff --git a/src/main/java/lambdasinaction/dsl/model/Order.java b/src/main/java/lambdasinaction/dsl/model/Order.java new file mode 100644 index 00000000..21c06747 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/model/Order.java @@ -0,0 +1,43 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl.model; + +import java.util.ArrayList; +import java.util.List; + +public class Order { + + private String customer; + + private List trades = new ArrayList<>(); + + public void addTrade( Trade trade ) { + trades.add( trade ); + } + + public String getCustomer() { + return customer; + } + + public void setCustomer( String customer ) { + this.customer = customer; + } + + public double getValue() { + return trades.stream().mapToDouble( Trade::getValue ).sum(); + } +} \ No newline at end of file diff --git a/src/main/java/lambdasinaction/dsl/model/Stock.java b/src/main/java/lambdasinaction/dsl/model/Stock.java new file mode 100644 index 00000000..1e0302e2 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/model/Stock.java @@ -0,0 +1,40 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl.model; + +public class Stock { + + private String symbol; + + private String market; + + public String getSymbol() { + return symbol; + } + + public void setSymbol( String symbol ) { + this.symbol = symbol; + } + + public String getMarket() { + return market; + } + + public void setMarket( String market ) { + this.market = market; + } +} diff --git a/src/main/java/lambdasinaction/dsl/model/Tax.java b/src/main/java/lambdasinaction/dsl/model/Tax.java new file mode 100644 index 00000000..d2d6bf22 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/model/Tax.java @@ -0,0 +1,31 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl.model; + +public class Tax { + public static double regional(double value) { + return value * 1.1; + } + + public static double general(double value) { + return value * 1.3; + } + + public static double surcharge(double value) { + return value * 1.05; + } +} diff --git a/src/main/java/lambdasinaction/dsl/model/Trade.java b/src/main/java/lambdasinaction/dsl/model/Trade.java new file mode 100644 index 00000000..c8f35813 --- /dev/null +++ b/src/main/java/lambdasinaction/dsl/model/Trade.java @@ -0,0 +1,66 @@ +/* + * Copyright 2005 JBoss Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package lambdasinaction.dsl.model; + +public class Trade { + + public enum Type { BUY, SELL } + + private Type type; + + private Stock stock; + + private int quantity; + + private double price; + + public Type getType() { + return type; + } + + public void setType( Type type ) { + this.type = type; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity( int quantity ) { + this.quantity = quantity; + } + + public double getPrice() { + return price; + } + + public void setPrice( double price ) { + this.price = price; + } + + public Stock getStock() { + return stock; + } + + public void setStock( Stock stock ) { + this.stock = stock; + } + + public double getValue() { + return quantity * price; + } +} From 5ff395e4987028a114f2345acc11cee36c2296d5 Mon Sep 17 00:00:00 2001 From: Mario Fusco Date: Wed, 23 Mar 2016 19:23:11 +0100 Subject: [PATCH 2/4] dsl chapter --- src/main/java/lambdasinaction/dsl/Grouping.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/lambdasinaction/dsl/Grouping.java b/src/main/java/lambdasinaction/dsl/Grouping.java index 698764d5..b1472cf0 100644 --- a/src/main/java/lambdasinaction/dsl/Grouping.java +++ b/src/main/java/lambdasinaction/dsl/Grouping.java @@ -16,7 +16,7 @@ package lambdasinaction.dsl; -import lambdasinaction.chap5.Dish; +import lambdasinaction.chap6.Dish; import java.util.List; import java.util.Map; @@ -24,7 +24,7 @@ import java.util.stream.Collector; import static java.util.stream.Collectors.groupingBy; -import static lambdasinaction.chap5.Dish.menu; +import static lambdasinaction.chap6.Dish.menu; import static lambdasinaction.dsl.Grouping.GroupingBuilder.groupOn; public class Grouping { From 4cd6b4d4de144e073758114b55493d8c3ebef852 Mon Sep 17 00:00:00 2001 From: Jorge Cabrera Date: Sat, 6 Aug 2016 11:31:03 -0700 Subject: [PATCH 3/4] Filter to return only low calorie dishes --- src/main/java/lambdasinaction/chap4/StreamBasic.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/lambdasinaction/chap4/StreamBasic.java b/src/main/java/lambdasinaction/chap4/StreamBasic.java index 9beea005..19a8c176 100644 --- a/src/main/java/lambdasinaction/chap4/StreamBasic.java +++ b/src/main/java/lambdasinaction/chap4/StreamBasic.java @@ -24,7 +24,7 @@ public static void main(String...args){ public static List getLowCaloricDishesNamesInJava7(List dishes){ List lowCaloricDishes = new ArrayList<>(); for(Dish d: dishes){ - if(d.getCalories() > 400){ + if(d.getCalories() < 400){ lowCaloricDishes.add(d); } } @@ -42,7 +42,7 @@ public int compare(Dish d1, Dish d2){ public static List getLowCaloricDishesNamesInJava8(List dishes){ return dishes.stream() - .filter(d -> d.getCalories() > 400) + .filter(d -> d.getCalories() < 400) .sorted(comparing(Dish::getCalories)) .map(Dish::getName) .collect(toList()); From 4786c46a24e2f7d0a749d34d585bb2c1d9f64c53 Mon Sep 17 00:00:00 2001 From: Mario Fusco Date: Fri, 24 Feb 2017 08:52:33 +0100 Subject: [PATCH 4/4] changes for 2nd edition --- pom.xml | 35 ++++++++++- .../chap10/OperationsWithOptional.java | 7 +++ .../lambdasinaction/chap10/OptionalMain.java | 11 ++++ src/main/java/lambdasinaction/chap6/Dish.java | 34 +++++++--- .../java/lambdasinaction/chap6/Grouping.java | 17 +++++ .../chap6/PartitionPrimeNumbers.java | 8 +-- .../chap7/ParallelStreamBenchmark.java | 62 +++++++++++++++++++ 7 files changed, 158 insertions(+), 16 deletions(-) create mode 100644 src/main/java/lambdasinaction/chap7/ParallelStreamBenchmark.java diff --git a/pom.xml b/pom.xml index 32ca0b3e..10e5035e 100644 --- a/pom.xml +++ b/pom.xml @@ -13,6 +13,16 @@ + + org.openjdk.jmh + jmh-core + 1.17.4 + + + org.openjdk.jmh + jmh-generator-annprocess + 1.17.4 + junit junit @@ -27,11 +37,30 @@ maven-compiler-plugin 3.1 - 1.8 - 1.8 + 1.9 + 1.9 + + org.apache.maven.plugins + maven-shade-plugin + + + package + + shade + + + benchmarks + + + org.openjdk.jmh.Main + + + + + + - \ No newline at end of file diff --git a/src/main/java/lambdasinaction/chap10/OperationsWithOptional.java b/src/main/java/lambdasinaction/chap10/OperationsWithOptional.java index de588759..d2940969 100644 --- a/src/main/java/lambdasinaction/chap10/OperationsWithOptional.java +++ b/src/main/java/lambdasinaction/chap10/OperationsWithOptional.java @@ -10,6 +10,13 @@ public class OperationsWithOptional { public static void main(String... args) { System.out.println(max(of(3), of(5))); System.out.println(max(empty(), of(5))); + + Optional opt1 = of(5); + Optional opt2 = opt1.or(() -> of(4)); + + System.out.println( + of(5).or(() -> of(4)) + ); } public static final Optional max(Optional i, Optional j) { diff --git a/src/main/java/lambdasinaction/chap10/OptionalMain.java b/src/main/java/lambdasinaction/chap10/OptionalMain.java index 1826cb4a..dcd97792 100644 --- a/src/main/java/lambdasinaction/chap10/OptionalMain.java +++ b/src/main/java/lambdasinaction/chap10/OptionalMain.java @@ -2,6 +2,8 @@ import java.util.*; +import static java.util.stream.Collectors.toSet; + public class OptionalMain { public String getCarInsuranceName(Optional person) { @@ -10,4 +12,13 @@ public String getCarInsuranceName(Optional person) { .map(Insurance::getName) .orElse("Unknown"); } + + public Set getCarInsuranceNames(List persons) { + return persons.stream() + .map(Person::getCar) + .map(optCar -> optCar.flatMap(Car::getInsurance)) + .map(optInsurance -> optInsurance.map(Insurance::getName)) + .flatMap(Optional::stream) + .collect(toSet()); + } } diff --git a/src/main/java/lambdasinaction/chap6/Dish.java b/src/main/java/lambdasinaction/chap6/Dish.java index a353f1bc..adba6e93 100644 --- a/src/main/java/lambdasinaction/chap6/Dish.java +++ b/src/main/java/lambdasinaction/chap6/Dish.java @@ -2,6 +2,8 @@ import java.util.*; +import static java.util.Arrays.asList; + public class Dish { private final String name; @@ -40,13 +42,27 @@ 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)); + 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)); + + public static final Map> dishTags = new HashMap<>(); + + static { + dishTags.put("pork", asList("greasy", "salty")); + dishTags.put("beef", asList("salty", "roasted")); + dishTags.put("chicken", asList("fried", "crisp")); + dishTags.put("french fries", asList("greasy", "fried")); + dishTags.put("rice", asList("light", "natural")); + dishTags.put("season fruit", asList("fresh", "natural")); + dishTags.put("pizza", asList("tasty", "salty")); + dishTags.put("prawns", asList("tasty", "roasted")); + dishTags.put("salmon", asList("delicious", "fresh")); + } } \ No newline at end of file diff --git a/src/main/java/lambdasinaction/chap6/Grouping.java b/src/main/java/lambdasinaction/chap6/Grouping.java index bedb3470..9105cc80 100644 --- a/src/main/java/lambdasinaction/chap6/Grouping.java +++ b/src/main/java/lambdasinaction/chap6/Grouping.java @@ -3,6 +3,7 @@ import java.util.*; import static java.util.stream.Collectors.*; +import static lambdasinaction.chap6.Dish.dishTags; import static lambdasinaction.chap6.Dish.menu; public class Grouping { @@ -11,6 +12,9 @@ enum CaloricLevel { DIET, NORMAL, FAT }; public static void main(String ... args) { System.out.println("Dishes grouped by type: " + groupDishesByType()); + System.out.println("Dish names grouped by type: " + groupDishNamesByType()); + System.out.println("Dish tags grouped by type: " + groupDishTagsByType()); + System.out.println("Caloric dishes grouped by type: " + groupCaloricDishesByType()); System.out.println("Dishes grouped by caloric level: " + groupDishesByCaloricLevel()); System.out.println("Dishes grouped by type and caloric level: " + groupDishedByTypeAndCaloricLevel()); System.out.println("Count dishes in groups: " + countDishesInGroups()); @@ -24,6 +28,19 @@ private static Map> groupDishesByType() { return menu.stream().collect(groupingBy(Dish::getType)); } + private static Map> groupDishNamesByType() { + return menu.stream().collect(groupingBy(Dish::getType, mapping(Dish::getName, toList()))); + } + + private static Map> groupDishTagsByType() { + return menu.stream().collect(groupingBy(Dish::getType, flatMapping(dish -> dishTags.get( dish.getName() ).stream(), toSet()))); + } + + private static Map> groupCaloricDishesByType() { +// return menu.stream().filter(dish -> dish.getCalories() > 500).collect(groupingBy(Dish::getType)); + return menu.stream().collect(groupingBy(Dish::getType, filtering(dish -> dish.getCalories() > 500, toList()))); + } + private static Map> groupDishesByCaloricLevel() { return menu.stream().collect( groupingBy(dish -> { diff --git a/src/main/java/lambdasinaction/chap6/PartitionPrimeNumbers.java b/src/main/java/lambdasinaction/chap6/PartitionPrimeNumbers.java index 5122a6a3..69d7c4ca 100644 --- a/src/main/java/lambdasinaction/chap6/PartitionPrimeNumbers.java +++ b/src/main/java/lambdasinaction/chap6/PartitionPrimeNumbers.java @@ -32,10 +32,10 @@ public static Map> partitionPrimesWithCustomCollector(int public static boolean isPrime(List primes, Integer candidate) { double candidateRoot = Math.sqrt((double) candidate); - //return primes.stream().filter(p -> p < candidateRoot).noneMatch(p -> candidate % p == 0); - return takeWhile(primes, i -> i <= candidateRoot).stream().noneMatch(i -> candidate % i == 0); + //return takeWhile(primes, i -> i <= candidateRoot).stream().noneMatch(i -> candidate % i == 0); + return primes.stream().takeWhile(i -> i <= candidateRoot).noneMatch(i -> candidate % i == 0); } - +/* public static List takeWhile(List list, Predicate p) { int i = 0; for (A item : list) { @@ -46,7 +46,7 @@ public static List takeWhile(List list, Predicate p) { } return list; } - +*/ public static class PrimeNumbersCollector implements Collector>, Map>> { diff --git a/src/main/java/lambdasinaction/chap7/ParallelStreamBenchmark.java b/src/main/java/lambdasinaction/chap7/ParallelStreamBenchmark.java new file mode 100644 index 00000000..cdd16aca --- /dev/null +++ b/src/main/java/lambdasinaction/chap7/ParallelStreamBenchmark.java @@ -0,0 +1,62 @@ +package lambdasinaction.chap7; + +import java.util.concurrent.TimeUnit; +import java.util.stream.LongStream; +import java.util.stream.Stream; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Level; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value=2, jvmArgs={"-Xms4G", "-Xmx4G"}) +@Measurement(iterations=2) +@Warmup(iterations=3) +public class ParallelStreamBenchmark { + + private static final long N = 10_000_000L; + + @Benchmark + public long iterativeSum() { + long result = 0; + for (long i = 1L; i <= N; i++) { + result += i; + } + return result; + } + + @Benchmark + public long sequentialSum() { + return Stream.iterate( 1L, i -> i + 1 ).limit(N).reduce( 0L, Long::sum ); + } + + @Benchmark + public long parallelSum() { + return Stream.iterate(1L, i -> i + 1).limit(N).parallel().reduce( 0L, Long::sum); + } + + @Benchmark + public long rangedSum() { + return LongStream.rangeClosed( 1, N ).reduce( 0L, Long::sum ); + } + + @Benchmark + public long parallelRangedSum() { + return LongStream.rangeClosed(1, N).parallel().reduce( 0L, Long::sum); + } + + @TearDown(Level.Invocation) + public void tearDown() { + System.gc(); + } +}