How to use BiPredicate with anyMatch()

Viewed 1134

I have a Set of Currencies as Set<String> and RequiredCurrency as Set<String> . I have to check if any of required currency is present in currency set or not . I have written BiPredicate for that as below and trying to use the same in anyMatch() . But it is not working for me. How can i achieve it .

Set<String> currencyValues = currencies.getCurrencies().values()
                    .stream()
                    .map(currencyEntity -> {
                       return currencyEntity.getNameOfSymbol();
                    }).collect(Collectors.toSet());

Set<String> requestCurrencyCodes = globalPricingRequests.stream().map(globalPricingRequest -> {
    return globalPricingRequest.getCurrencyISOCode();
}).collect(Collectors.toSet());

BiPredicate<Set<String>, String> checkIfCurrencyPresent = Set::contains;

boolean isCurrencyCodeValid = requestCurrencyCodes.stream().anyMatch(checkIfCurrencyPresent.test(currencyValues));

I am unable to pass the requestCurrencyCode in checkIfCurrencyPresent.test(currencyValues).

4 Answers

You don't need a BiPredicate. Rather a simple Predicate would do it.

Predicate<String> checkIfCurrencyPresent = currencyValues::contains;

boolean isCurrencyCodeValid = requestCurrencyCodes.stream()
        .anyMatch(checkIfCurrencyPresent);

And here's a more condensed version.

boolean isCurrencyCodeValid = requestCurrencyCodes.stream()
        .anyMatch(currencyValues::contains);

The Stream.anyMatch method takes a Predicate, not a BiPredicate. Therefore you cannot use a BiPredicate directly with anyMatch. From the code you've shown you don't need a BiPredicate anyway. Just do:

boolean isCurrencyCodeValid = requestCurrencyCodes.stream()
        .anyMatch(currencyValues::contains);

If you really want to use a BiPredicate for some reason you can do:

BiPredicate<Set<String>, String> checkIfCurrencyPresent = Set::contains;
boolean isCurrencyCodeValid = requestCurrencyCodes.stream()
        .anyMatch(code -> checkIfCurrencyPresent.test(currencyValues, code));

However, I don't know why you'd want to do that. All it does is wrap a BiPredicate in a Predicate.

Though ideally I would as well have preferred using Predicate here, yet if you were to make a generic method that could be used in multiple situations, you could have spared yourself from the wrapping up of BiPredicate within a Predicate using the following utility method:

private static boolean checkIfCurrencyPresent(Set<String> set, String currency) {
    return set.contains(currency);
}

and then consumed it using a lambda as :

boolean isCurrencyCodeValid = requestCurrencyCodes
        .stream()
        .anyMatch(a -> checkIfCurrencyPresent(currencyValues,a));

such that it doesn't rely on testing a string against a specific Set and you could use it generically enough as:

boolean isCurrencyCodeValidInverseExample = currencyValues // any collcetion of string
        .stream()
        .anyMatch(a -> checkIfCurrencyPresent(requestCurrencyCodes, a)); // different set as an input

Aside: The first two lines of your code could possibly be made more readable as something like(assuming model names) :

Set<String> currencyValues = currencies.getCurrencies().values()
        .stream()
        .map(CurrencyEntity::getNameOfSymbol)
        .collect(Collectors.toSet());

Set<String> requestCurrencyCodes = globalPricingRequests.stream()
        .map(GlobalPricingRequest::getCurrencyISOCode)
        .collect(Collectors.toSet());

Just to add on the good answers provided so far. you can accomplish the said requirement via Collections.disjoint:

boolean isCurrencyCodeValid = !Collections.disjoint(currencyValues, requestCurrencyCodes);

isCurrencyCodeValid will be true if any value in currencyValues is present in requestCurrencyCodes otherwise false.

Full code:

Set<String> currencyValues = currencies.getCurrencies().values()
                              .stream()
                              .map(CurrencyEntity::getNameOfSymbol)
                              .collect(toSet());

Set<String> requestCurrencyCodes = globalPricingRequests.stream()
        .map(GlobalPricingRequest::getCurrencyISOCode)
        .collect(toSet());

boolean isCurrencyCodeValid = !Collections.disjoint(currencyValues, requestCurrencyCodes);
Related