6

In isReadyToDeliver method if all products in order is available (ProductState.AVAILABLE) and if order state is ready to send (OrderState.READY_TO_SEND), method must return true. I wrote both two part but I couldn't combine them in return phrase,

I wrote return orderState.andThen(productState) but get this error:

The method andThen(Function<? super Boolean,? extends V>) in the type Function<Order,Boolean> is not applicable for the arguments (Function<Order,Boolean>)

public class OrderFunctions  {

    public Function<Order, Boolean> isReadyToDeliver() {            
        Function<Order, Boolean> orderState = o -> o.getState() == OrderState.READY_TO_SEND;            
        Function<Order, Boolean>  productState = 
                o -> o.getProducts()
                    .stream()
                    .map(Product -> Product.getState())
                    .allMatch(Product -> Product == ProductState.AVAILABLE);

        return ????? ; 
       //return  orderState.andThen(productState);
       //error: The method andThen(Function<? super Boolean,? extends V>) in the type Function<Order,Boolean> is not applicable for the arguments (Function<Order,Boolean>)      
    }
}

In case other classes are needed:

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

enum ProductType { NORMAL, BREAKABLE, PERISHABLE }

public class Order {

    private OrderState state;
    private List<Product> products = new ArrayList<>();

    public OrderState getState() {
        return state;
    }

    public void setState(OrderState state) {
        this.state = state;
    }

    public Order state(OrderState state) {
        this.state = state;
        return this;
    }

    public List<Product> getProducts() {
        return products;
    }

    public void setProducts(List<Product> products) {
        this.products = products;
    }

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

public class Product {

    private String code;
    private String title;
    private ProductState state;

    public ProductState getState() {
        return state;
    }

    public void setState(ProductState state) {
        this.state = state;
    }

    public Product state(ProductState state) {
        this.state = state;
        return this;
    }
}
2
  • 1
    You're using Function where you should be using Predicate. docs.oracle.com/javase/8/docs/api/java/util/function/… Commented Jan 20, 2018 at 16:00
  • 2
    Minor note: please surround code text with ` rather than ** to make it fixed-width and obviously code to readers. Commented Jan 20, 2018 at 17:57

2 Answers 2

6

If you change isReadyToDeliver() to return Predicate<Order> then you will be able to combine two predicates with .and(Predicate another) function:

public Predicate<Order> isReadyToDeliver() {
    Predicate<Order> orderState = o -> o.getState() == OrderState.READY_TO_SEND;

    Predicate<Order> productState =
                o -> o.getProducts()
                   .stream()
                   .map(Product -> Product.getState())
                   .allMatch(Product -> Product == ProductState.AVAILABLE);

    return orderState.and(productState);
}

Your example with functions composition didn't work, because when you compose functions f and g, g takes as a parameter value that f function returns. In your case it was broken, because orderState expected Order and return Boolean and it this case orderState.andThen() expected a function that takes Boolean as a parameter and returns something else. This requirement was not satisfied, because productState expected Order and returned Boolean. This is exactly what following error said:

error: The method andThen(Function) in the type Function is not applicable for the arguments (Function)

But if for some reason you want to stay with Function<Order, Boolean> then you will have return a lambda like:

public Function<Order, Boolean> isReadyToDeliver() {
    Function<Order, Boolean> orderState = o -> o.getState() == OrderState.READY_TO_SEND;

    Function<Order, Boolean> productState =
            o -> o.getProducts()
                    .stream()
                    .map(Product -> Product.getState())
                    .allMatch(Product -> Product == ProductState.AVAILABLE);


    return (order) -> orderState.apply(order) && productState.apply(order);
}
Sign up to request clarification or add additional context in comments.

Comments

2

From the two functions orderState and productState you can create a new lambda expression by using && (the logical and) and return it:

public Function<Order, Boolean> isReadyToDeliver() {

    Function<Order, Boolean> orderState = ...;

    Function<Order, Boolean>  productState = ...;


    return o -> orderState.apply(o) && productState.apply(o);
} 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.