如何将 BiPredicate 与 anyMatch() 一起使用

How to use BiPredicate with anyMatch()

我有一组货币 Set<String> 和 RequiredCurrency 作为 Set<String> 。我必须检查 currency set 中是否存在任何所需的货币。我已经为此编写了 BiPredicate 如下所示,并尝试在 anyMatch() 中使用相同的内容。但这对我不起作用。我怎样才能实现它。

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

我无法在 checkIfCurrencyPresent.test(currencyValues) 中传递 requestCurrencyCode。

您不需要 BiPredicate。一个简单的 Predicate 就可以做到。

Predicate<String> checkIfCurrencyPresent = currencyValues::contains;

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

这里有一个更精简的版本。

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

Stream.anyMatch 方法采用 Predicate,而不是 BiPredicate。因此,您不能将 BiPredicate 直接与 anyMatch 一起使用。从您显示的代码中,您无论如何都不需要 BiPredicate 。只要做:

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

如果出于某种原因你真的想使用 BiPredicate,你可以这样做:

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

但是,我不知道你为什么要这样做。它所做的只是将 BiPredicate 包装在 Predicate.

虽然理想情况下我也希望 在这里,但是如果您要制作一个可以在多种情况下使用的通用方法,您可以避免 结束BiPredicatePredicate 中使用以下实用方法:

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

然后使用 lambda 将其消耗为:

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

这样它就不会依赖于针对特定 Set 测试字符串,您可以将其足够通用地用作:

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

旁白:您的代码的前两行可能会变得更具可读性,例如(假设模型名称):

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

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

只是为了补充目前提供的好的答案。您可以通过 Collections.disjoint:

完成上述要求
boolean isCurrencyCodeValid = !Collections.disjoint(currencyValues, requestCurrencyCodes);
如果 currencyValues 中的任何值出现在 requestCurrencyCodes 中,

isCurrencyCodeValid 将为真,否则为假。

完整代码:

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