在Java 8中如何结合函数和谓词?

3

isBigOrder方法中,如果订单中产品的总价值大于1000,则必须返回true。如何使用Java 8编写代码?我已经编写了求和部分,但无法完成。

public Function<Order, Boolean> isBigOrder() {

        Function<Order, Optional<Long>> sum = a -> a.getProducts()
                .stream()
                .map(P -> P.getPrice())
                .reduce((p1,p2)->p1+p2);

        Predicate <Optional<Long>> isBig =  x -> x.get() > 1000 ;

        return ????;
    }

如果需要其他类:

enum OrderState { CONFIRMED, PAID, WAREHOUSE_PROCESSED, READY_TO_SEND, DELIVERED }

enum ProductType { NORMAL, BREAKABLE, PERISHABLE }

public class Product {
    private String code;
    private String title;
    private long price;
    private ProductState state;
    private ProductType type;

    //all fields have getter and setter

    public Product price(long price) {
        this.price = price;
        return this;
    }
}

public class Order {

    private String code;
    private long price;
    private String buyyer;
    private OrderState state;
    private List<Product> products = new ArrayList<>();

    //all fields have getter and setter

    public Order price(long price) {
        this.price = price;
        return this;
    }

    public Order product(Product product) {
        if (products == null) {
            products = new ArrayList<>();
        }
        products.add(product);
        return this;
    }    
}

为什么要返回 Function<Order, Boolean>?相比于返回 boolean 并将方法放在 Order 类中,有什么优势呢? - Kayaman
1
你的 if (products == null) { products = new ArrayList<>(); } 语句已经过时了,因为你总是用 ArrayList 初始化 products 字段。如果你想确保没有人会将其覆盖为 null,请将其声明为 final - Holger
2
另外一方面需要注意的是,a -> { long value = 0; for(Product p: a.getProducts()) { value += p.getPrice(); if(value>1000) return true; } return false; } 不是很适合使用 stream,但是更有效率,因为它在超过阈值时可以立即返回,而不必继续处理所有元素。 - Holger
2个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
9
你不需要使用Predicate。只需计算总和并检查它是否大于1000即可。
public Function<Order, Boolean> isBigOrder() {
    return o -> o.getProducts()
                 .stream()
                 .mapToLong(Product::getPrice)
                 .sum() > 1000;
}

或者,正如Holger所评论的那样,当您想要实现一个具有单个参数并返回boolean的函数时,Predicate接口是一个更合适的函数式接口:

public Predicate<Order> isBigOrder() {
    return o -> o.getProducts()
                 .stream()
                 .mapToLong(Order::getPrice)
                 .sum() > 1000;
}

5

假设在编写代码时,由于两个功能来自不同的位置无法合并,你可以按照以下方式进行合并:

public static Function<Order,Boolean> combine(
    Function<Order, Optional<Long>> f
,   Predicate <Optional<Long>> pred
) {
    return a -> pred.test(f.apply(a));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,