Reputation: 1203
How can i write below code using lambda expression in java8. I am new to 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");
}
}
}
I have tried the below code as yet as per the suggestion . Is there any other thing which we can improve in this code to write it using lambdas more.
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;
}
Upvotes: 5
Views: 239
Reputation: 31878
You could use stream twice and improve the readability of your code as :
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");
}
Upvotes: 2
Reputation: 18245
Your problem is not with lambdas, but with code organisation. You have a data, i.e. List<GlobalPricingRequest>
and a set of validation rules. All you need to do it to apply these valdation rules to the given data.
This approach give you flexibility to add or remove validation rules easily. And test or check each rule separately.
Optimal solution is to split each validation into separate class.
First, create a manager and interface for validation rule:
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);
}
}
Second, implement each validation rule in the separate class (was added to the manager):
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 code:
GlobalPricingRequestValidationManager validationManager = new GlobalPricingRequestValidationManager();
List<GlobalPricingRequest> globalPricingRequests = Collections.emptyList();
validationManager.validate(globalPricingRequests);
Upvotes: 4
Reputation: 56423
This type of validation you're performing is better via the imperative approach nevertheless we can utilise lambdas where appropriate.
First, I would isolate the repetitive conditions to a local predicate with the use of signum
as also suggested by @Thomas Kläger under the post as it's more appropriate in this specific case than intValue
.
Predicate<BigDecimal> criteria = b -> b != null && b.signum() < 0;
Then your imperative approach would look like:
for (GlobalPricingRequest globalPricingRequest : globalPricingRequests) {
isValidOrElseThrowBadRequestException(globalPricingRequest.getFeePerTransact(), criteria);
for (EventTypePricingMapping eventTypePricingMapping : globalPricingRequest.getEventTypePricingList()) {
isValidOrElseThrowBadRequestException(eventTypePricingMapping.getFeePerRevenue(), criteria);
}
}
Where isValidOrElseThrow
is defined as:
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");
}
Just with a few isolations here and there we're able to make the code more readable.
Upvotes: 2
Reputation: 3232
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
});
});
Upvotes: 0