【问题标题】:Combine a Function and a Predicate in Java 8在 Java 8 中结合函数和谓词
【发布时间】:2018-07-01 02:07:54
【问题描述】:

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&lt;Order, Boolean&gt;?与返回 boolean 并将方法放入 Order 类相比有什么优势?
  • 您的if (products == null) { products = new ArrayList&lt;&gt;(); } 语句已经完全过时,因为您总是使用ArrayList 初始化products 字段。如果您想确保没有人用null 覆盖它,请声明它final...
  • 另外附带说明,a -&gt; { long value = 0; for(Product p: a.getProducts()) { value += p.getPrice(); if(value&gt;1000) return true; } return false; } 不是流式传输,而是更高效,因为它可以在超过阈值时立即返回,而不是不必要地继续处理所有元素。

标签: java java-8 functional-programming predicate functional-interface


【解决方案1】:

您不需要Predicate。只需计算总和并检查它是否 > 1000。

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

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

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

【讨论】:

    【解决方案2】:

    假设你在写的状态下不能把这两个函数组合起来,比如因为它们来自不同的地方,你可以把它们组合成如下:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-21
      • 1970-01-01
      相关资源
      最近更新 更多