Java Streams在reduce之后对值进行排序

时间:2018-03-06 12:44:56

标签: java java-8 java-stream

我只是试着理解Java中的流,我坚持排序阶段。 我的目的是用一条流来获得最昂贵的蔬菜披萨。在这一点上,我得到披萨价格,但我无法对它进行排序。谁能告诉我应该怎么做呢?

我试着用这个:

AppActivate ThisWorkbook.Name

此代码返回未分类的披萨值。

3 个答案:

答案 0 :(得分:5)

import java.util.Collection;
import java.util.Comparator;

interface Pizza {
    interface Ingredient {
        boolean isMeat();

        int getPrice();
    }

    Collection<Ingredient> getIngredients();

    static boolean isVegetarian(Pizza pizza) {
        return pizza.getIngredients().stream().noneMatch(Ingredient::isMeat);
    }

    static int price(Pizza pizza) {
        return pizza.getIngredients().stream().mapToInt(Ingredient::getPrice).sum();
    }

    static Pizza mostExpensiveVegetarianPizza(Collection<Pizza> pizzas) {
        return pizzas.stream()
                     .filter(Pizza::isVegetarian)
                     .max(Comparator.comparingInt(Pizza::price))
                     .orElseThrow(() -> new IllegalArgumentException("no veggie pizzas"));
    }
}

如果您希望Ingredient.getPrice()返回double,则可以使用Stream.mapToDouble()中的Pizza.price()Comparator.comparingDouble()中的Pizza.mostExpensiveVegetarianPizza()

答案 1 :(得分:4)

要找到价格最高的披萨,您需要在每次比较价格时计算每个披萨的价格,或者有一个存储披萨和价格的物品。

这是一个使用匿名对象来保存我们需要比萨饼及其价格的临时状态的解决方案:

Optional<Pizza> pizza = pizzas.stream()

        .filter(p -> p.getIngredients().stream()
                .noneMatch(Ingredient::isMeat)) // filter

        .map(p -> new Object() { // anonymous object to hold (pizza, price)

            Pizza pizza = p; // store pizza

            int price = p.getIngredients().stream()
                    .mapToInt(Ingredient::getPrice).sum(); // store price
        })

        .max(Comparator.comparingInt(o -> o.price)) // find the highest price
        .map(o -> o.pizza); // get the corresponding pizza

答案 2 :(得分:3)

我做了一个简短的功能示例。我在Pizza类中封装了一些流来提高易读性。

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

输出

  

比萨[name = special;成本= 51.25 $]

如果您不喜欢干净的代码,可以使用

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

编辑:使用reduce选择最大值披萨的表达式基于Urma,Fusco和Mycroft的书籍“ Java 8 in action ”中的清单5.8(第110页)。一本好书! : - )