4

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).

Ousmane D.
  • 54,915
  • 8
  • 91
  • 126
Ishant Gaurav
  • 1,183
  • 2
  • 13
  • 32
  • 2
    `Stream.anyMatch` takes a `Predicate`, not a `BiPredicate`. That said, using `anyMatch(currencyValues::contains)` should fit your needs. – Slaw Jan 05 '19 at 05:35
  • 1
    `anyMatch` get `Predicate` as argument. so you should pass `Predicate` instead `BiPredicate` – Hadi J Jan 05 '19 at 05:38
  • This was the exact reason why I suggested **if** you need a `Predicate`, [how you could use it.](https://stackoverflow.com/a/54040692/1746118). So precisely, you just needed a `Predicate` in your current use case and not a `BiPredicate`. – Naman Jan 05 '19 at 07:30

4 Answers4

2

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);
Ravindra Ranwala
  • 20,744
  • 6
  • 45
  • 63
1

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.

Slaw
  • 37,820
  • 8
  • 53
  • 80
1

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());
Naman
  • 27,789
  • 26
  • 218
  • 353
0

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);
Ousmane D.
  • 54,915
  • 8
  • 91
  • 126