0

Given: list of Customers (with Supplier and Agency fields), String agency, String supplier.

Goal: check if any customer supports given agency AND given supplier.

I have a stream that needs to be filtered twice (by two values). If stream is empty after first filtering, I need to check it and throw exception. If it's not empty, I need to process it through second filter (and then check again if it's not empty).

I want to avoid collecting stream to lists if it's possible (and I can't use anyMatch or count methods because they are terminal)

Currently my code look's like:

void checkAgencySupplierMapping(String agency, String supplier) {
   List<Customers> customersFilteredByAgency = allCustomers.stream()
             .filter(customer -> customer.getAgency().equals(agency))
             .collect(toList());

   if (customersFilteredByAgency.isEmpty()) throw new AgencyNotSupportedException(agency);

   customersFilteredByAgency.stream()
             .filter(customer -> customer.getSupplier().equals(supplier))
             .findFirst().orElseThrow(() -> throw new SupplierNotSupportedException(supplier);
}

In this example I skipped some technical details about filtering (eg. parsing Supplier to String).

And I want to achieve something like this:

void checkAgencySupplierMapping(String agency, String supplier) {
    allCustomers.stream()
       .filter(customer -> customer.getAgency().equals(agency))
       .ifEmpty( () -> throw new AgencyNotSupportedException(agency) )
       .filter( customer -> customer.getSupplier().equals(supplier)
       .ifEmpty( () -> throw new SupplierNotSupportedException(supplier); // or findFirst().orElseThrow...
}

Is there any Java 8 feature that will let me checking my Stream status without terminating it?

2

2 Answers 2

2

The code below is a bit ugly but work like you wish.

First we need to count how many agency of customers match with and then try found the first one supplier match. If there are no matches throw an exception, but here you will check if the cause is that no agency clients were found in order to throw the correct excaption.

AtomicInteger countAgencyMatches = new AtomicInteger(0);

allCustomers.stream()
        .filter(customer -> {
            if (customer.getAgency().equals(agency)) {
                countAgencyMatches.incrementAndGet();
                return true;
            }

            return false;
        })
        .filter(customer -> customer.getSupplier().equals(supplier))
        .findFirst()
        .orElseThrow(() -> {
            if (countAgencyMatches.get() == 0) {
                return new AgencyNotSupportedException(agency);
            }

            return new SupplierNotSupportedException(supplier);
        });
Sign up to request clarification or add additional context in comments.

Comments

0

In Java 8, there is no direct way to check if a stream is empty without terminating it. You can achieve the desired behavior by using a custom utility method to handle the intermediate checks. Something like:

public void checkAgencySupplierMapping(List<Customer> allCustomers, String agency, String supplier) {
    Stream<Customer> stream = allCustomers.stream()
        .filter(customer -> customer.getAgency().equals(agency));
    
    stream = checkIfEmpty(stream, () -> new AgencyNotSupportedException(agency));
    
    stream.filter(customer -> customer.getSupplier().equals(supplier))
          .findFirst()
          .orElseThrow(() -> new SupplierNotSupportedException(supplier));
}

And the helper method...

    private <T> Stream<T> checkIfEmpty(Stream<T> stream, Supplier<RuntimeException> exceptionSupplier) {
        boolean isEmpty = stream.findAny().isEmpty();
        if (isEmpty) {
            throw exceptionSupplier.get();
        }
        return stream;
    }

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.