Конвертировать цикл в лямбду и выдать исключение - PullRequest
0 голосов
/ 05 января 2019

Как я могу написать код ниже, используя лямбда-выражение в java8. Я новичок в 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");
        }
    }
}

Я попробовал приведенный ниже код в соответствии с предложением. Есть ли что-то еще, что мы можем улучшить в этом коде, чтобы написать его, используя больше лямбда-выражений.

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 голосов
/ 05 января 2019

Этот тип проверки, который вы выполняете, лучше с помощью императивного подхода, тем не менее, мы можем использовать лямбды, где это уместно.

Во-первых, я бы выделил повторяющиеся условия для локального предиката с использованием signum, что также было предложено @Thomas Kläger в статье, поскольку в данном конкретном случае это более уместно, чем intValue.

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

С помощью нескольких отрывков, мы можем сделать код более читабельным.

0 голосов
/ 05 января 2019
globalPricingRequest.forEach(data -> {
      if (data.getFeePerTransact() != null && data.getFeePerTransact().intValue() < 0) {
        // you can only throw unchecked exception in lambda function
        throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
      }
      data.getEventTypePricingList().forEach(event-> {
        if (event.getFeePerRevenue() != null && event.getFeePerRevenue().intValue() < 0) {
          // you can only throw unchecked exception in lambda function
          throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
        }// this if statemnt in your code is twice
      });
    });
0 голосов
/ 05 января 2019

Задача

Ваша проблема не с лямбдами, а с организацией кода. У вас есть данные, то есть 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);
0 голосов
/ 05 января 2019

Вы можете использовать stream дважды и улучшить читабельность своего кода как:

Predicate<BigDecimal> feeCheck =
        feePerTransactOrRevenue -> feePerTransactOrRevenue != null
                && feePerTransactOrRevenue.intValue() < 0;

boolean globalRequestCheck = globalPricingRequests.stream()
        .map(GlobalPricingRequest::getFeePerTransact)
        .anyMatch(feeCheck); 

boolean eventTypeCheck = globalPricingRequests.stream()
        .map(GlobalPricingRequest::getEventTypePricingList)
        .flatMap(List::stream)
        .map(EventTypePricingMapping::getFeePerRevenue)
        .anyMatch(feeCheck);

// if any of the element matches the condition, throw the exception
if (globalRequestCheck || eventTypeCheck) { 
    throw ExceptionHelper.badRequest("Fee Per Transaction can't be less than zero");
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...