I've made a short functional example. I have encapsulated some streams inside Pizza class to improve legibility.
INGREDIENT
public class Ingredient {
private String name;
private double price;
private boolean meat;
public Ingredient(String name, double price, boolean meat) {
this.name = name;
this.price = price;
this.meat = meat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public boolean isMeat() {
return meat;
}
public void setMeat(boolean meat) {
this.meat = meat;
}
}
PIZZA
public class Pizza {
private String name;
private List<Ingredient> ingredients;
public Pizza(String name, List<Ingredient> ingredients) {
this.name = name;
this.ingredients = ingredients;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Ingredient> getIngredients() {
return ingredients;
}
public void setIngredients(List<Ingredient> ingredients) {
this.ingredients = ingredients;
}
public boolean isVegan() {
return (ingredients != null) ? ingredients.stream().noneMatch(Ingredient::isMeat)
: false;
}
public double getTotalCost() {
return (ingredients != null) ? ingredients.stream().map(Ingredient::getPrice)
.reduce(0.0, Double::sum)
: 0;
}
@Override
public String toString() {
return "Pizza [name=" + name + "; cost=" + getTotalCost() +"$]";
}
}
MAIN
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
public class VeganPizzaPlace {
public static void checkMostExpensiveVeganPizza(List<Pizza> pizzas) {
if (pizzas != null) {
Optional<Pizza> maxVegan =
pizzas.stream()
.filter(Pizza::isVegan)
.max(Comparator.comparingDouble(Pizza::getTotalCost));
if (maxVegan.isPresent()) {
System.out.println(maxVegan.get().toString());
} else {
System.out.println("No vegan pizzas in the menu today");
}
}
}
public static void main (String[] args) {
List<Pizza> pizzas = new ArrayList<Pizza>();
Ingredient tomato = new Ingredient("tomato", 0.50, false);
Ingredient cheese = new Ingredient("cheese", 0.75, false);
Ingredient broccoli = new Ingredient("broccoli", 50.00, false);
Ingredient ham = new Ingredient("ham", 10.00, true);
List<Ingredient> ingredientsMargherita = new ArrayList<Ingredient>();
ingredientsMargherita.add(tomato);
ingredientsMargherita.add(cheese);
Pizza margherita = new Pizza("margherita", ingredientsMargherita);
List<Ingredient> ingredientsSpecial = new ArrayList<Ingredient>();
ingredientsSpecial.add(tomato);
ingredientsSpecial.add(cheese);
ingredientsSpecial.add(broccoli);
Pizza special = new Pizza("special", ingredientsSpecial);
List<Ingredient> ingredientsProsciutto = new ArrayList<Ingredient>();
ingredientsProsciutto.add(tomato);
ingredientsProsciutto.add(cheese);
ingredientsProsciutto.add(ham);
Pizza prosciutto = new Pizza("prosciutto", ingredientsProsciutto);
pizzas.add(margherita);
pizzas.add(special);
pizzas.add(prosciutto);
checkMostExpensiveVeganPizza(pizzas);
}
}
OUTPUT
Pizza [name=special; cost=51.25$]
If you do not like clean code, you can use instead
Optional<Pizza> maxVegan =
pizzas.stream()
.filter(p -> p.getIngredients().stream().noneMatch(Ingredient::isMeat))
.reduce((p1, p2) -> p1.getIngredients().stream().map(Ingredient::getPrice).reduce(0.0, Double::sum)
< p2.getIngredients().stream().map(Ingredient::getPrice).reduce(0.0, Double::sum) ? p1 : p2);
EDIT: Expression for selecting max valued pizza using a reduce
is based on listing 5.8 (page 110) from the book "Java 8 in action" by Urma, Fusco and Mycroft. A great book! :-)