Java Streams在reduce之后对值进行排序
我只是试着理解Java中的流,我停留在排序阶段。 我的目的是用一条溪流得到最昂贵的蔬菜比萨饼。在这一点上,我得到了比萨饼的价格,但我不能排序。谁能告诉我该怎么做 我试着这样做:Java Streams在reduce之后对值进行排序,java,java-8,java-stream,Java,Java 8,Java Stream,我只是试着理解Java中的流,我停留在排序阶段。 我的目的是用一条溪流得到最昂贵的蔬菜比萨饼。在这一点上,我得到了比萨饼的价格,但我不能排序。谁能告诉我该怎么做 我试着这样做: pizzas.stream() .flatMap(pizza -> Stream.of(pizza.getIngredients()) .filter(list -> list.stream().noneMatch(Ingredient::isMeat)) .m
pizzas.stream()
.flatMap(pizza -> Stream.of(pizza.getIngredients())
.filter(list -> list.stream().noneMatch(Ingredient::isMeat))
.map(list -> list.stream().map(Ingredient::getPrice).reduce(0,(a, b) -> a + b))
.sorted((o1, o2) -> o1.intValue() - o2.intValue())
)
.forEach(System.out::println);
此代码返回比萨饼的未排序值。import java.util.Collection;
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"));
}
}
导入java.util.Comparator;
界面比萨饼{
界面成分{
布尔isMeat();
int getPrice();
}
收集材料();
静态布尔值是素食者(比萨饼){
返回pizza.get配料().stream().noneMatch(配料::isMeat);
}
静态整数价格(比萨饼){
返回pizza.get配料().stream().mapToInt(配料::getPrice.sum();
}
静态比萨莫斯特克斯素食比萨(集合比萨){
return pizzas.stream()
.filter(比萨饼::Is素食)
.max(比较器比较(比萨饼:价格))
.orElseThrow(()->新的IllegalArgumentException(“无蔬菜比萨饼”);
}
}
如果希望
component.getPrice()
返回一个double
,可以在Pizza.price()
中使用Stream.mapToDouble()
和Comparator.comparingDouble()
中使用Pizza.mostexpensivevegetrainepizza()
中的。我将一些流封装在Pizza类中以提高易读性
配料
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;
}
}
披萨
公共级比萨饼{
私有字符串名称;
私人成分清单;
公共比萨饼(串名、配料表){
this.name=名称;
这个。成分=成分;
}
公共字符串getName(){
返回名称;
}
公共void集合名(字符串名){
this.name=名称;
}
公共列表{
返回成分;
}
公共成分(列出成分){
这个。成分=成分;
}
公共布尔值isVegan(){
返回(配料!=null)?配料.stream().noneMatch(配料::isMeat)
:假;
}
公共双getTotalCost(){
返回(配料!=null)?配料.stream().map(配料::getPrice)
.reduce(0.0,Double::sum)
: 0;
}
@凌驾
公共字符串toString(){
返回“Pizza[name=“+name+”;cost=“+getTotalCost()+”$”;
}
}
主要
import java.util.ArrayList;
导入java.util.Comparator;
导入java.util.List;
导入java.util.Optional;
公共级素食比萨广场{
公共静态无效检查mostexpensiveveganpizza(列出pizzas){
如果(比萨饼!=null){
可选maxVegan=
pizzas.stream()
.过滤器(比萨饼::isVegan)
.max(Comparator.comparingDouble(Pizza::getTotalCost));
if(maxVegan.isPresent()){
System.out.println(maxVegan.get().toString());
}否则{
System.out.println(“今天菜单上没有纯素比萨饼”);
}
}
}
公共静态void main(字符串[]args){
List pizzas=new ArrayList();
成分番茄=新成分(“番茄”,0.50,假);
成分奶酪=新成分(“奶酪”,0.75,假);
成分西兰花=新成分(“西兰花”,50.00,假);
成分火腿=新成分(“火腿”,10.00,真实);
List INGREDIENTSMARGERITA=新数组列表();
添加(番茄);
添加(奶酪);
披萨玛格丽塔=新披萨(“玛格丽塔”,意为“玛格丽塔”);
List ingredientsSpecial=new ArrayList();
添加特殊成分(番茄);
添加特殊成分(奶酪);
特别添加(西兰花);
比萨特价=新比萨(“特价”,IngCreditsSpecial);
List ingredientsProsciutto=新数组列表();
加入(西红柿);
添加(奶酪);
添加(火腿);
比萨火腿=新比萨(“火腿”,IngreditsProsciutto);
比萨加(玛格丽塔);
比萨饼。添加(特殊);
比萨。加(火腿);
checkmostexpensiveveganpizzas(比萨);
}
}
输出
比萨饼[名称=特殊;成本=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);
可选maxVegan=
pizzas.stream()
.filter(p->p.GetComponents().stream().noneMatch(配料::isMeat))
.reduce((p1,p2)->p1.getComponents().stream().map(component::getPrice)。reduce(0.0,Double::sum)
编辑:使用reduce
选择最大值比萨饼的表达式基于Urma、Fusco和Mycroft的《Java8在行动》一书中的清单5.8(第110页)。一本好书!:-) 要找到价格最高的比萨饼,您需要在每次比较价格时计算每个比萨饼的价格,或者有一个存储比萨饼和价格的对象
这里有一个解决方案,它使用匿名对象来保存我们需要比萨饼及其价格的临时状态:
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
Optional pizza=pizzas.stream()
.filter(p->p.getComponents().stream())
.noneMatch(成分::isMeat))//过滤器
.map(p->new Object(){//要保存的匿名对象(比萨饼,价格)
比萨饼=p;//比萨饼店
int price=p.getComponents().stream()
.mapToInt(配料::getPrice).sum();//存储价格
})
.max(Comparator.comparingit(o->o.price))//查找最高价格
.map(o->o.pizza);//得到相应的比萨饼
为什么不在映射后使用Stream.max
?而不是排序?不。您需要首先将比萨饼
映射到类似条目的东西
和
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);
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