将循环转换为lambda并引发异常

时间:2019-01-05 11:36:56

标签: java lambda java-8 java-stream

如何在Java8中使用Lambda表达式编写以下代码。我是Java 8的新手。

for (GlobalPricingRequest globalPricingRequest : globalPricingRequests) {
    BigDecimal feePerTrans = globalPricingRequest.getFeePerTransact();
    if (feePerTrans != null && feePerTrans.intValue() < 0) {
        throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
    }
    List<EventTypePricingMapping> eventTypePricingMappings = globalPricingRequest.getEventTypePricingList();
    for (EventTypePricingMapping eventTypePricingMapping : eventTypePricingMappings) {
        BigDecimal feePerRevenue = eventTypePricingMapping.getFeePerRevenue();
        if (feePerRevenue != null && feePerRevenue.intValue() < 0) {
            throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
        }
        if (eventTypePricingMapping.getFeePerRevenue().intValue() < 0) {
            throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
        }
    }
}

我已经按照建议尝试了以下代码。我们还有什么可以改进的代码,可以使用lambdas编写更多代码。

globalPricingRequests.forEach((globalPricingRequest) -> {
    if (checkIfValueLessThanZero(globalPricingRequest.getFeePerTransact())) {
        throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
    }
    List<EventTypePricingMapping> eventTypePricingMappings = globalPricingRequest.getEventTypePricingList();
    eventTypePricingMappings.forEach((eventTypePricingMapping) -> {
        if (checkIfValueLessThanZero(eventTypePricingMapping.getFeePerRevenue())) {
            throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
        }
        if (checkIfValueLessThanZero(eventTypePricingMapping.getFeePerReg())) {
            throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
        }
    });
});


private boolean checkIfValueLessThanZero(Object object) {
    if (object instanceof BigDecimal) {
       if (object != null && ((BigDecimal) object).intValue() < 0) {
           return true;
       }
    }
    return false;
}

4 个答案:

答案 0 :(得分:4)

问题

您的问题不是lambda,而是代码组织。您有一个数据,即List<GlobalPricingRequest>一组验证规则。您需要执行所有操作以将这些评估规则应用于给定数据。

这种方法使您可以灵活地轻松添加或删除验证规则。然后分别测试或检查每个规则。

解决方案

最佳解决方案是将每个验证分成单独的类。

首先,创建验证规则的管理器和界面:

public final class GlobalPricingRequestValidationManager {

    private final List<ValidationRule> validationRules =
            Arrays.asList(
                new TransactionFeeEqualOrGreaterThanZeroValidationRule(),
                new RevenueFeeEqualOrGreaterThanZeroValidationRule());

    public void validate(List<GlobalPricingRequest> globalPricingRequests) {
        validationRules.forEach(validationRule -> validationRule.validate(globalPricingRequests));
    }

    public interface ValidationRule {

        void validate(List<GlobalPricingRequest> globalPricingRequests);
    }

}

第二,在单独的类中实现每个验证规则(已添加到管理器中):

public final class TransactionFeeEqualOrGreaterThanZeroValidationRule implements GlobalPricingRequestValidationManager.ValidationRule {

    @Override
    public void validate(List<GlobalPricingRequest> globalPricingRequests) {
        if (globalPricingRequests.stream()
                                 .map(GlobalPricingRequest::getFeePerTransact)
                                 .filter(Objects::nonNull)
                                 .anyMatch(val -> val.signum() == -1)))
            throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
    }
}

public final class RevenueFeeEqualOrGreaterThanZeroValidationRule implements GlobalPricingRequestValidationManager.ValidationRule {

    @Override
    public void validate(List<GlobalPricingRequest> globalPricingRequests) {
        if (globalPricingRequests.stream()
                                 .map(GlobalPricingRequest::getEventTypePricingList)
                                 .flatMap(List::stream)
                                 .map(EventTypePricingMapping::getFeePerRevenue)
                                 .filter(Objects::nonNull)
                                 .anyMatch(val -> val.signum() == -1)))
            throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");

    }
}

Clinet代码:

GlobalPricingRequestValidationManager validationManager = new GlobalPricingRequestValidationManager();
List<GlobalPricingRequest> globalPricingRequests = Collections.emptyList();
validationManager.validate(globalPricingRequests);

答案 1 :(得分:2)

您可以使用 stream两次,并提高代码的可读性:

Try

答案 2 :(得分:2)

通过命令式方法,您正在执行的这种类型的验证会更好,但是我们可以在适当的地方使用lambda。

首先,我将使用signum将重复条件隔离到本地谓词,正如@ThomasKläger在帖子中所建议的那样,因为在这种特定情况下比intValue更合适。 / p>

Predicate<BigDecimal> criteria = b -> b != null && b.signum() < 0;

然后您的命令式方法将如下所示:

for (GlobalPricingRequest globalPricingRequest : globalPricingRequests) {
      isValidOrElseThrowBadRequestException(globalPricingRequest.getFeePerTransact(), criteria);
      for (EventTypePricingMapping eventTypePricingMapping : globalPricingRequest.getEventTypePricingList()) {
          isValidOrElseThrowBadRequestException(eventTypePricingMapping.getFeePerRevenue(), criteria);
      }
}

isValidOrElseThrow的定义为:

public static void isValidOrElseThrowBadRequestException(BigDecimal data, Predicate<BigDecimal> criteria) throws Exception { // change the exception to the specific one you're using 
       if(criteria.test(data)) throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
}

只需在此处进行一些隔离,就可以使代码更具可读性。

答案 3 :(得分:0)

@results = Item.search(
             'Query',
             where: {consumer_type: 'User', consumer_id: current_user.id},
             load:  false
           )