如何使用Java 8流验证列表中的对象值是否不为空或不为null。

huangapple go评论81阅读模式
英文:

How to validate object values in a List if value is not empty or not null using java 8 stream

问题

// Original Code:
I have an objectList

OfferToCheck offer = new OfferToCheck();

offer.setDiscountId(null);
offer.setProductName("sadf spacefjkd");
offer.setServiceCode("dfsdfv");
offer.setServiceGroup("nospace");

OfferToCheck offer1 = new OfferToCheck();
offer1.setDiscountId("");
offer1.setProductName("sadfspacefjkd");
offer1.setServiceCode("sdnof");
offer1.setServiceGroup("sdf");

request.setOffersToCheck(Arrays.asList(offer, offer1));
request.setStartTrialPeriod("y");
if (service.validateStatus(request)) {
    System.out.println("true");
} else {
    System.out.println("false");
}

// Original Loop:
for (OfferToCheck offer : request.getOffersToCheck()) {
    if (offer.getDiscountId() != null && !offer.getProductName().isEmpty()) {
        if (!offer.getDiscountId().chars().allMatch(Character::isDigit)) {
            return isValid = false;
        }
    }
    if (offer.getServiceCode() != null && !offer.getServiceCode().isEmpty()) {
        if (!offer.getServiceCode().chars().allMatch(Character::isAlphabetic)) {
            return isValid = false;
        }
    }
    if (offer.getServiceGroup() != null && !offer.getServiceGroup().isEmpty()) {
        if (!offer.getServiceGroup().chars().allMatch(Character::isAlphabetic)) {
            return isValid = false;
        }
    }
    if (offer.getProductName() != null && !offer.getProductName().isEmpty()) {
        if (!offer.getProductName().matches("[a-zA-Z ]*")) {
            return isValid = false;
        }
    }
}

// Stream Approach:
if (!request.getOffersToCheck().stream()
        .filter(list -> list.getDiscountId() != null && !list.getDiscountId().isEmpty())
        .filter(list -> list.getProductName() != null && !list.getProductName().isEmpty())
        .allMatch(validateList -> (
                validateList.getDiscountId().chars().allMatch(Character::isLetterOrDigit) &&
                validateList.getProductName().matches("[a-zA-Z0-9 ]*") &&
                validateList.getServiceCode().matches("[a-zA-Z0-9]*") &&
                validateList.getServiceGroup().chars().allMatch(Character::isDigit))
        )) {
    return isValid = false;
}

Note: The provided code snippets appear to be a mix of original code, a for loop, and a stream approach. If there are any errors in the original code or the provided snippets, please adjust them accordingly.

英文:

I have an objectList

	OfferToCheck offer = new OfferToCheck();
offer.setDiscountId(null);
offer.setProductName("sadf spacefjkd");
offer.setServiceCode("dfsdfv");
offer.setServiceGroup("nospace");
OfferToCheck offer1 = new OfferToCheck();
offer1.setDiscountId("");
offer1.setProductName("sadfspacefjkd");
offer1.setServiceCode("sdnof");
offer1.setServiceGroup("sdf");
request.setOffersToCheck(Arrays.asList(offer,offer1));		
request.setStartTrialPeriod("y");
if(service.validateStatus(request)){
System.out.println("true");
}
else{
System.out.println("false");
}

i want to acheive this for loop using java 8 stream

for(OfferToCheck offer : request.getOffersToCheck()){
if(offer.getDiscountId() != null && !offer.getProductName().isEmpty()){
if(!offer.getDiscountId().chars().allMatch(Character::isDigit)){
return isValid = false;
}
}
if(offer.getServiceCode() != null && !offer.getServiceCode().isEmpty()){
if(!offer.getServiceCode().chars().allMatch(Character::isAlphabetic)){
return isValid = false;
}
}
if(offer.getServiceGroup() != null && !offer.getServiceGroup().isEmpty()){
if(!offer.getServiceGroup().chars().allMatch(Character::isAlphabetic)){
return isValid = false;
}
}
if(offer.getProductName() != null && !offer.getProductName().isEmpty()){
if(!offer.getProductName().matches("[a-zA-Z ]*")){
return isValid = false;
}
}
}

I have tried this but when value of discountId is empty or null it does not include the rest of the object into the stream.

	if(!request.getOffersToCheck().stream()
.filter(list -> (list.getServiceCode() != null && !list.getServiceCode().isEmpty()))
.filter  (list -> list.getDiscountId() != null && !list.getDiscountId().isEmpty()) 
.filter  (list -> list.getProductName() != null && !list.getProductName().isEmpty())
.filter (list -> list.getProductName() != null && !list.getProductName().isEmpty()) 
.filter (list -> list.getServiceGroup() != null && !list.getServiceGroup().isEmpty())
.allMatch(validateList -> (validateList .getDiscountId().chars().allMatch(Character::isLetterOrDigit)
&& validateList.getProductName().matches("[a-zA-Z0-9 ]*")
&& validateList.getServiceCode().matches("[a-zA-Z0-9]*")
&& validateList.getServiceGroup().chars().allMatch(Character::isDigit))
))
{
return isValid = false;
}

also tried all the condtion in one filter

答案1

得分: 1

你可以创建一个字段映射的地图(使用 Function 作为键,Predicate 作为字段验证的值)。

然后,你只需遍历报价(Stream<OfferToCheck>),对于每个报价遍历代表提取和验证的地图。

  • 使用键提取字段值(例如,String fieldValue = entry.getKey().apply(offer)
  • 使用值验证字段值(例如,entry.getValue().test(fieldValue)

你想收集 Stream::allMatch 的所有布尔结果,并确保它们都为 true,从而返回该结果本身。

Map<Function<OfferToCheck, String>, Predicate<String>> map = new HashMap<>();
map.put(OfferToCheck::getDiscountId, s -> s.chars().allMatch(Character::isDigit));
map.put(OfferToCheck::getServiceCode, s -> s.chars().allMatch(Character::isAlphabetic));
map.put(OfferToCheck::getServiceGroup, s -> s.chars().allMatch(Character::isAlphabetic));
map.put(OfferToCheck::getProductName, s -> s.matches("[a-zA-Z ]*"));

return request.getOffersToCheck()
     .stream()
     .allMatch(offer -> map.entrySet()
              .stream()
              .filter(entry -> entry.getKey().apply(offer) != null && 
                              !entry.getKey().apply(offer).isEmpty())
              .allMatch(entry -> entry.getValue().test(entry.getKey().apply(offer))));

此解决方案假设所有字段都以类似的方式进行验证 - 例如,使用了 String::isEmpty。否则,您必须将此类验证放入映射中,并从内部流中删除它。根据您的需要随意修改代码。

是否采用此解决方案的最终选择完全取决于您:

优点

  • 对于大量类似的字段验证非常有用,例如 SOAP。
  • 可扩展:每个新字段都只需添加一个新的 map 条目。

缺点

  • 阅读、维护和调试较困难(必须使用 Stream::peek)。
  • 需要适当的单元测试来覆盖这种逻辑(无论如何,我建议您这样做,这种实现方式需要强烈的测试需求)。
英文:

You can create a map of the field mappings (using Function) as a key and a Predicate as a value of the field validation itself.

Then all you need is to iterate through the offers (Stream&lt;OfferToCheck&gt;) and for each one iterate through the map which represents both the extraction and the validation itself.

  • Using it's key you extract the field value (i.e. String fieldValue = entry.getKey().apply(offer))
  • Using it's value you validate the field value (i.e. entry.getValue().test(fieldValue))

You want to collect all the boolean results from Stream::allMatch and get sure they are all true, thus returning that result itself.

Map&lt;Function&lt;OfferToCheck, String&gt;, Predicate&lt;String&gt;&gt; map = new HashMap&lt;&gt;();
map.put(OfferToCheck::getDiscountId, s -&gt; s.chars().allMatch(Character::isDigit));
map.put(OfferToCheck::getServiceCode, s -&gt; s.chars().allMatch(Character::isAlphabetic));
map.put(OfferToCheck::getServiceGroup, s -&gt; s.chars().allMatch(Character::isAlphabetic));
map.put(OfferToCheck::getProductName, s -&gt; s.matches(&quot;[a-zA-Z ]*&quot;));
return request.getOffersToCheck()
.stream()
.allMatch(offer -&gt; map.entrySet()
.stream()
.filter(entry -&gt; entry.getKey().apply(offer) != null &amp;&amp; 
!entry.getKey().apply(offer).isEmpty())
.allMatch(entry -&gt; entry.getValue().test(entry.getKey().apply(offer))));

This solution assumes all the fields are validated in the similar way - ex. String::isEmpty is used. Otherwise you have to place such validation to the map and remove it from the inner Stream. Feel free to modify the code according to your needs.

The final choice whether you are up to this solution is solely up to you:

Pros

  • Useful for a large number of similar field validations, ex. SOAP.
  • Scalable: the only thing you add with each new field is a new map entry.

Cons

  • Harder to read, maintain and debug (you have to use Stream::peek).
  • Needs proper unit tests to cover such logic (I'd recommend you anyway, this implementation implies a strong need for a test).

huangapple
  • 本文由 发表于 2020年9月21日 16:01:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/63988288.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定