Java 8 alternative for validating data inside multiple nested loops
Clash Royale CLAN TAG#URR8PPP
up vote
8
down vote
favorite
I have a question regarding validating data in a nested for loop.
public class Object1
private String obj1Name;
private String obj1Desc;
private List<Object2> object2List;
//Setters and getters
public class Object2
private String obj2Name;
private String obj2Desc;
private List<Object3> object3List;
//Setters and getters
public class Object3
private String obj3Name;
private String obj3Desc;
//Setters and getters
I wish to validate both name
and desc
in all objects, instead of using a nested loop like the following:
List<Object1> object1List = getObject1List();
for(Object1 object1 : object1List )
if(object1.getObj1Name() == null)
//throw error
if(object1.getObj1Desc() == null)
//throw error
for(Object2 object2 : object1.getObject2List())
if(object2.getObj2Name() == null)
//throw error
if(object2.getObj2Desc() == null)
//throw error
//loop Object 3 ...
Is there any better way to do it?
java java-8
|
show 2 more comments
up vote
8
down vote
favorite
I have a question regarding validating data in a nested for loop.
public class Object1
private String obj1Name;
private String obj1Desc;
private List<Object2> object2List;
//Setters and getters
public class Object2
private String obj2Name;
private String obj2Desc;
private List<Object3> object3List;
//Setters and getters
public class Object3
private String obj3Name;
private String obj3Desc;
//Setters and getters
I wish to validate both name
and desc
in all objects, instead of using a nested loop like the following:
List<Object1> object1List = getObject1List();
for(Object1 object1 : object1List )
if(object1.getObj1Name() == null)
//throw error
if(object1.getObj1Desc() == null)
//throw error
for(Object2 object2 : object1.getObject2List())
if(object2.getObj2Name() == null)
//throw error
if(object2.getObj2Desc() == null)
//throw error
//loop Object 3 ...
Is there any better way to do it?
java java-8
7
are you throwing the same error on each condition ? if so, what type of error?
– Aomine
Dec 5 at 12:42
yes, throwing same error on each condition, the error will beInvalidParameterException
– hades
Dec 5 at 13:10
You might find useful docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
– Federico Piazza
Dec 5 at 13:22
3
don't get me wrong but have you considered a framework with support for@NotNull
?
– Eugene
Dec 5 at 13:28
@Eugene Exactly what I wanted to point out as well. I mean that's what something likejavax.validation.constraints
are meant for.
– nullpointer
Dec 5 at 13:33
|
show 2 more comments
up vote
8
down vote
favorite
up vote
8
down vote
favorite
I have a question regarding validating data in a nested for loop.
public class Object1
private String obj1Name;
private String obj1Desc;
private List<Object2> object2List;
//Setters and getters
public class Object2
private String obj2Name;
private String obj2Desc;
private List<Object3> object3List;
//Setters and getters
public class Object3
private String obj3Name;
private String obj3Desc;
//Setters and getters
I wish to validate both name
and desc
in all objects, instead of using a nested loop like the following:
List<Object1> object1List = getObject1List();
for(Object1 object1 : object1List )
if(object1.getObj1Name() == null)
//throw error
if(object1.getObj1Desc() == null)
//throw error
for(Object2 object2 : object1.getObject2List())
if(object2.getObj2Name() == null)
//throw error
if(object2.getObj2Desc() == null)
//throw error
//loop Object 3 ...
Is there any better way to do it?
java java-8
I have a question regarding validating data in a nested for loop.
public class Object1
private String obj1Name;
private String obj1Desc;
private List<Object2> object2List;
//Setters and getters
public class Object2
private String obj2Name;
private String obj2Desc;
private List<Object3> object3List;
//Setters and getters
public class Object3
private String obj3Name;
private String obj3Desc;
//Setters and getters
I wish to validate both name
and desc
in all objects, instead of using a nested loop like the following:
List<Object1> object1List = getObject1List();
for(Object1 object1 : object1List )
if(object1.getObj1Name() == null)
//throw error
if(object1.getObj1Desc() == null)
//throw error
for(Object2 object2 : object1.getObject2List())
if(object2.getObj2Name() == null)
//throw error
if(object2.getObj2Desc() == null)
//throw error
//loop Object 3 ...
Is there any better way to do it?
java java-8
java java-8
edited Dec 6 at 4:17
Boann
36.6k1287121
36.6k1287121
asked Dec 5 at 12:36
hades
69411030
69411030
7
are you throwing the same error on each condition ? if so, what type of error?
– Aomine
Dec 5 at 12:42
yes, throwing same error on each condition, the error will beInvalidParameterException
– hades
Dec 5 at 13:10
You might find useful docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
– Federico Piazza
Dec 5 at 13:22
3
don't get me wrong but have you considered a framework with support for@NotNull
?
– Eugene
Dec 5 at 13:28
@Eugene Exactly what I wanted to point out as well. I mean that's what something likejavax.validation.constraints
are meant for.
– nullpointer
Dec 5 at 13:33
|
show 2 more comments
7
are you throwing the same error on each condition ? if so, what type of error?
– Aomine
Dec 5 at 12:42
yes, throwing same error on each condition, the error will beInvalidParameterException
– hades
Dec 5 at 13:10
You might find useful docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
– Federico Piazza
Dec 5 at 13:22
3
don't get me wrong but have you considered a framework with support for@NotNull
?
– Eugene
Dec 5 at 13:28
@Eugene Exactly what I wanted to point out as well. I mean that's what something likejavax.validation.constraints
are meant for.
– nullpointer
Dec 5 at 13:33
7
7
are you throwing the same error on each condition ? if so, what type of error?
– Aomine
Dec 5 at 12:42
are you throwing the same error on each condition ? if so, what type of error?
– Aomine
Dec 5 at 12:42
yes, throwing same error on each condition, the error will be
InvalidParameterException
– hades
Dec 5 at 13:10
yes, throwing same error on each condition, the error will be
InvalidParameterException
– hades
Dec 5 at 13:10
You might find useful docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
– Federico Piazza
Dec 5 at 13:22
You might find useful docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
– Federico Piazza
Dec 5 at 13:22
3
3
don't get me wrong but have you considered a framework with support for
@NotNull
?– Eugene
Dec 5 at 13:28
don't get me wrong but have you considered a framework with support for
@NotNull
?– Eugene
Dec 5 at 13:28
@Eugene Exactly what I wanted to point out as well. I mean that's what something like
javax.validation.constraints
are meant for.– nullpointer
Dec 5 at 13:33
@Eugene Exactly what I wanted to point out as well. I mean that's what something like
javax.validation.constraints
are meant for.– nullpointer
Dec 5 at 13:33
|
show 2 more comments
6 Answers
6
active
oldest
votes
up vote
4
down vote
I am just going to say it here, so that no one does what you want to do - use a proper framework for this, personally I would go for Hibernate Validator - super easy to integrate and use IMO. It will support that nesting that you have without any problems and there are tons of tutorials online (even their own is good) and how to achieve that; hint: a few dependencies and a few annotations and you are done.
yeah, i actually know about hibernate validator, normally i use it to validate object request in@RequestBody
.
– hades
Dec 5 at 13:43
Thanks for the reminder, it don't come into my mind because i thought there is no way triggering the validation process, but it actually has.
– hades
Dec 5 at 14:20
add a comment |
up vote
3
down vote
EDIT: An idea to externalize the check, you need to create Functional Interface
ObjectValidatorInterface ov = new ObjectValidator();
if(!object1List.stream().allMatch(o -> ov.validate(o, Object1.class)))
// throw error;
And the interface
@FunctionalInterface
interface ObjectValidatorInterface
boolean validate(Object object, Class clazz);
class ObjectValidator implements ObjectValidatorInterface
public boolean validate(Object object, Class clazz)
boolean valid = false;
if(Object1.class.getName().equals(clazz.getName()))
valid = validateObject1((Object1) object);
else if(Object2.class.getName().equals(clazz.getName()))
valid = validateObject2((Object2) object);
else if(Object3.class.getName().equals(clazz.getName()))
valid = validateObject3((Object3) object);
return valid;
private boolean validateObject1(Object1 o)
boolean valid;
valid = o.getObj1Name() != null && o.getObj1Desc() != null;
if(!(o.getObject2List() == null
private boolean validateObject2(Object2 o)
private boolean validateObject3(Object3 o)
return o.getObj3Name() != null && o.getObj3Desc() != null;
ORIGINAL ANSWER
You might be able to do it by delegating the validation to each object:
List<Object1> object1List = getObject1List();
if(!object1List.stream().allMatch(Object1::isValid))
//throw error
And add an isValid
method to each object
public class Object1
private String obj1Name;
private String obj1Desc;
private List<Object2> object2List;
public boolean isValid()
return obj1Name != null
&& obj1Desc != null
&& object2List.stream().allMatch(Object2::isValid);
public class Object2
private String obj2Name;
private String obj2Desc;
private List<Object3> object3List;
public boolean isValid()
return obj2Name != null
&& obj2Desc != null
&& object3List.stream().allMatch(Object3::isValid);
public class Object3
private String obj3Name;
private String obj3Desc;
public boolean isValid()
return obj3Name != null
&& obj3Desc != null;
3
I really dislike this - you put the validation conditions inside the POJO itself - is this ever a good idea? what if there are 100 of these?
– Eugene
Dec 5 at 13:24
good one, but I think theseisValid
methods should be moved out of the POJO classes
– Andrew Tobilko
Dec 5 at 13:24
@Bentaye nope, the field names are different - this would not work
– Eugene
Dec 5 at 13:27
@Eugene Added an other version where the check is done by an external object
– Bentaye
Dec 5 at 14:22
@Bentaye well that is a bit better, I agree. But now, imagine supporting that and testing it correctly, with at least 10 different validation types and rules... you might be on the verge of the next mission impossible movie, which I would not want to be part of
– Eugene
Dec 5 at 14:23
|
show 1 more comment
up vote
1
down vote
Well, you can definitely avoid the "nesting" by using the Stream API:
if(object1List.stream()
.anyMatch(a -> a.getObj1Name() == null ||
a.getObj1Desc() == null))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObj2Name() == null ||
b.getObj2Desc() == null)))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObject3List().stream()
.anyMatch(c -> c.getObj3Name() == null ||
c.getObj3Desc() == null))))
// throw error
Another approach being more compact, but probably less efficient:
boolean result = object1List.stream()
.flatMap(a -> a.getObject2List().stream()
.flatMap(b -> b.getObject3List().stream()
.flatMap(c -> Stream.of(a.getObj1Name(),
a.getObj1Desc(), b.getObj2Name(),
b.getObj2Desc(), c.getObj3Name(), c.getObj3Desc()))))
.anyMatch(Objects::isNull);
if(result) // throw error
So, to conclude if performance is a concern then proceed with your approach or try and see if the parallel stream API can do you any good, otherwise, the above should suffice.
6
to me, it's way worse than OP's approach
– Andrew Tobilko
Dec 5 at 13:12
1
@AndrewTobilko the goal was to remove the nesting, and even in terms of efficiency that really depends on the number of elements in the source.
– Aomine
Dec 5 at 13:14
2
Yeah, flatmap that shit.
– michid
Dec 5 at 13:24
add a comment |
up vote
1
down vote
A validator, as a functional interface, is a Consumer
which consumes a value of a specific type, performs checks and throws an Exception if something is off.
Traversal of the data structure (Tree) can be accomplished over streams (peek
to visit a node, flatmap
to recurse into the children). For the validation, we introduce a NO-OP map operation, which validates and returns the value, allowing the stream to continue.
BiConsumer<String, Object> checkRequired = (name, value) ->
if (value == null)
throw new IllegalArgumentException(name + " is required");
;
Consumer<Object1> obj1Validator = obj1 ->
checkRequired.accept("Object1", obj1);
checkRequired.accept("obj1Name", obj1.getObj1Name());
checkRequired.accept("obj1Desc", obj1.getObj1Desc());
;
Consumer<Object2> obj2Validator = obj2 ->
checkRequired.accept("Object2", obj2);
checkRequired.accept("obj2Name", obj2.getObj2Name());
checkRequired.accept("obj2Desc", obj2.getObj2Desc());
;
Consumer<Object3> obj3Validator = obj3 ->
checkRequired.accept("Object3", obj3);
checkRequired.accept("obj3Name", obj3.getObj3Name());
checkRequired.accept("obj3Desc", obj3.getObj3Desc());
;
Object1 obj1 = ...; // assign some value
Stream.of(obj1)
.peek(obj1Validator)
.filter(x -> x.getObject2List() != null)
.map(Object1::getObject2List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj2Validator)
.map(Object2::getObject3List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj3Validator)
.count();
now imagine supporting this for numerous rules and fields... seriously, don't.
– Eugene
Dec 5 at 13:40
@Eugene that's what validation is about - check each model and each field. Of course that validation can be delegated to a framework, such as using Bean Validation (JSR-380) which drives field validations over annotations.
– Peter Walser
Dec 5 at 13:47
would you write this code or use a framework? that was my point
– Eugene
Dec 5 at 13:48
I would certainly use a framework, in particular Bean Validation (JSR-380, beanvalidation.org/specification)
– Peter Walser
Dec 5 at 14:07
add a comment |
up vote
0
down vote
Well, you could use a function/loop which sifts through an object(The generic Object). That way, you won't have to run a separate for loop for each object if the name of the member variable "desc" is uniform in all the three objects. But that's another level of nesting so not sure you'd want to use that if you're just looking to avoid nesting.
add a comment |
up vote
0
down vote
If their validation seems to be the same, only the type change, then use interface have Object1
, Object2
and Object3
implements ICommon
:
interface ICommon
String getField1();
int getField2();
Iterable<? extends ICommon> getChildren();
Then have this:
private void validate0(String prefix, ICommon common)
if (common.getField1() == null) throw new ValidationException(prefix + ".field1 can't be null");
if (common.getField2() == null) throw new ValidationException(prefix + ".field2 can't be null");
int index = 0;
for (ICommon child : getChildren())
validate0(prefix + ".children[" + index + "]", child);
++index;
public void validate(ICommon common)
validate0("common", common);
You may also invert this using a BiConsumer<String, ICommon>
(or Consumer<ICommon>
) to validate if you don't care about proper error reporting).
- This will also make it clearer about which validation may apply on your object
- Using stream does not (always) make it clearer (see Peter Walser answer and try to understand the big stream :)).
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53632516%2fjava-8-alternative-for-validating-data-inside-multiple-nested-loops%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
6 Answers
6
active
oldest
votes
6 Answers
6
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
4
down vote
I am just going to say it here, so that no one does what you want to do - use a proper framework for this, personally I would go for Hibernate Validator - super easy to integrate and use IMO. It will support that nesting that you have without any problems and there are tons of tutorials online (even their own is good) and how to achieve that; hint: a few dependencies and a few annotations and you are done.
yeah, i actually know about hibernate validator, normally i use it to validate object request in@RequestBody
.
– hades
Dec 5 at 13:43
Thanks for the reminder, it don't come into my mind because i thought there is no way triggering the validation process, but it actually has.
– hades
Dec 5 at 14:20
add a comment |
up vote
4
down vote
I am just going to say it here, so that no one does what you want to do - use a proper framework for this, personally I would go for Hibernate Validator - super easy to integrate and use IMO. It will support that nesting that you have without any problems and there are tons of tutorials online (even their own is good) and how to achieve that; hint: a few dependencies and a few annotations and you are done.
yeah, i actually know about hibernate validator, normally i use it to validate object request in@RequestBody
.
– hades
Dec 5 at 13:43
Thanks for the reminder, it don't come into my mind because i thought there is no way triggering the validation process, but it actually has.
– hades
Dec 5 at 14:20
add a comment |
up vote
4
down vote
up vote
4
down vote
I am just going to say it here, so that no one does what you want to do - use a proper framework for this, personally I would go for Hibernate Validator - super easy to integrate and use IMO. It will support that nesting that you have without any problems and there are tons of tutorials online (even their own is good) and how to achieve that; hint: a few dependencies and a few annotations and you are done.
I am just going to say it here, so that no one does what you want to do - use a proper framework for this, personally I would go for Hibernate Validator - super easy to integrate and use IMO. It will support that nesting that you have without any problems and there are tons of tutorials online (even their own is good) and how to achieve that; hint: a few dependencies and a few annotations and you are done.
edited Dec 5 at 19:18
answered Dec 5 at 13:39
Eugene
67.6k997160
67.6k997160
yeah, i actually know about hibernate validator, normally i use it to validate object request in@RequestBody
.
– hades
Dec 5 at 13:43
Thanks for the reminder, it don't come into my mind because i thought there is no way triggering the validation process, but it actually has.
– hades
Dec 5 at 14:20
add a comment |
yeah, i actually know about hibernate validator, normally i use it to validate object request in@RequestBody
.
– hades
Dec 5 at 13:43
Thanks for the reminder, it don't come into my mind because i thought there is no way triggering the validation process, but it actually has.
– hades
Dec 5 at 14:20
yeah, i actually know about hibernate validator, normally i use it to validate object request in
@RequestBody
.– hades
Dec 5 at 13:43
yeah, i actually know about hibernate validator, normally i use it to validate object request in
@RequestBody
.– hades
Dec 5 at 13:43
Thanks for the reminder, it don't come into my mind because i thought there is no way triggering the validation process, but it actually has.
– hades
Dec 5 at 14:20
Thanks for the reminder, it don't come into my mind because i thought there is no way triggering the validation process, but it actually has.
– hades
Dec 5 at 14:20
add a comment |
up vote
3
down vote
EDIT: An idea to externalize the check, you need to create Functional Interface
ObjectValidatorInterface ov = new ObjectValidator();
if(!object1List.stream().allMatch(o -> ov.validate(o, Object1.class)))
// throw error;
And the interface
@FunctionalInterface
interface ObjectValidatorInterface
boolean validate(Object object, Class clazz);
class ObjectValidator implements ObjectValidatorInterface
public boolean validate(Object object, Class clazz)
boolean valid = false;
if(Object1.class.getName().equals(clazz.getName()))
valid = validateObject1((Object1) object);
else if(Object2.class.getName().equals(clazz.getName()))
valid = validateObject2((Object2) object);
else if(Object3.class.getName().equals(clazz.getName()))
valid = validateObject3((Object3) object);
return valid;
private boolean validateObject1(Object1 o)
boolean valid;
valid = o.getObj1Name() != null && o.getObj1Desc() != null;
if(!(o.getObject2List() == null
private boolean validateObject2(Object2 o)
private boolean validateObject3(Object3 o)
return o.getObj3Name() != null && o.getObj3Desc() != null;
ORIGINAL ANSWER
You might be able to do it by delegating the validation to each object:
List<Object1> object1List = getObject1List();
if(!object1List.stream().allMatch(Object1::isValid))
//throw error
And add an isValid
method to each object
public class Object1
private String obj1Name;
private String obj1Desc;
private List<Object2> object2List;
public boolean isValid()
return obj1Name != null
&& obj1Desc != null
&& object2List.stream().allMatch(Object2::isValid);
public class Object2
private String obj2Name;
private String obj2Desc;
private List<Object3> object3List;
public boolean isValid()
return obj2Name != null
&& obj2Desc != null
&& object3List.stream().allMatch(Object3::isValid);
public class Object3
private String obj3Name;
private String obj3Desc;
public boolean isValid()
return obj3Name != null
&& obj3Desc != null;
3
I really dislike this - you put the validation conditions inside the POJO itself - is this ever a good idea? what if there are 100 of these?
– Eugene
Dec 5 at 13:24
good one, but I think theseisValid
methods should be moved out of the POJO classes
– Andrew Tobilko
Dec 5 at 13:24
@Bentaye nope, the field names are different - this would not work
– Eugene
Dec 5 at 13:27
@Eugene Added an other version where the check is done by an external object
– Bentaye
Dec 5 at 14:22
@Bentaye well that is a bit better, I agree. But now, imagine supporting that and testing it correctly, with at least 10 different validation types and rules... you might be on the verge of the next mission impossible movie, which I would not want to be part of
– Eugene
Dec 5 at 14:23
|
show 1 more comment
up vote
3
down vote
EDIT: An idea to externalize the check, you need to create Functional Interface
ObjectValidatorInterface ov = new ObjectValidator();
if(!object1List.stream().allMatch(o -> ov.validate(o, Object1.class)))
// throw error;
And the interface
@FunctionalInterface
interface ObjectValidatorInterface
boolean validate(Object object, Class clazz);
class ObjectValidator implements ObjectValidatorInterface
public boolean validate(Object object, Class clazz)
boolean valid = false;
if(Object1.class.getName().equals(clazz.getName()))
valid = validateObject1((Object1) object);
else if(Object2.class.getName().equals(clazz.getName()))
valid = validateObject2((Object2) object);
else if(Object3.class.getName().equals(clazz.getName()))
valid = validateObject3((Object3) object);
return valid;
private boolean validateObject1(Object1 o)
boolean valid;
valid = o.getObj1Name() != null && o.getObj1Desc() != null;
if(!(o.getObject2List() == null
private boolean validateObject2(Object2 o)
private boolean validateObject3(Object3 o)
return o.getObj3Name() != null && o.getObj3Desc() != null;
ORIGINAL ANSWER
You might be able to do it by delegating the validation to each object:
List<Object1> object1List = getObject1List();
if(!object1List.stream().allMatch(Object1::isValid))
//throw error
And add an isValid
method to each object
public class Object1
private String obj1Name;
private String obj1Desc;
private List<Object2> object2List;
public boolean isValid()
return obj1Name != null
&& obj1Desc != null
&& object2List.stream().allMatch(Object2::isValid);
public class Object2
private String obj2Name;
private String obj2Desc;
private List<Object3> object3List;
public boolean isValid()
return obj2Name != null
&& obj2Desc != null
&& object3List.stream().allMatch(Object3::isValid);
public class Object3
private String obj3Name;
private String obj3Desc;
public boolean isValid()
return obj3Name != null
&& obj3Desc != null;
3
I really dislike this - you put the validation conditions inside the POJO itself - is this ever a good idea? what if there are 100 of these?
– Eugene
Dec 5 at 13:24
good one, but I think theseisValid
methods should be moved out of the POJO classes
– Andrew Tobilko
Dec 5 at 13:24
@Bentaye nope, the field names are different - this would not work
– Eugene
Dec 5 at 13:27
@Eugene Added an other version where the check is done by an external object
– Bentaye
Dec 5 at 14:22
@Bentaye well that is a bit better, I agree. But now, imagine supporting that and testing it correctly, with at least 10 different validation types and rules... you might be on the verge of the next mission impossible movie, which I would not want to be part of
– Eugene
Dec 5 at 14:23
|
show 1 more comment
up vote
3
down vote
up vote
3
down vote
EDIT: An idea to externalize the check, you need to create Functional Interface
ObjectValidatorInterface ov = new ObjectValidator();
if(!object1List.stream().allMatch(o -> ov.validate(o, Object1.class)))
// throw error;
And the interface
@FunctionalInterface
interface ObjectValidatorInterface
boolean validate(Object object, Class clazz);
class ObjectValidator implements ObjectValidatorInterface
public boolean validate(Object object, Class clazz)
boolean valid = false;
if(Object1.class.getName().equals(clazz.getName()))
valid = validateObject1((Object1) object);
else if(Object2.class.getName().equals(clazz.getName()))
valid = validateObject2((Object2) object);
else if(Object3.class.getName().equals(clazz.getName()))
valid = validateObject3((Object3) object);
return valid;
private boolean validateObject1(Object1 o)
boolean valid;
valid = o.getObj1Name() != null && o.getObj1Desc() != null;
if(!(o.getObject2List() == null
private boolean validateObject2(Object2 o)
private boolean validateObject3(Object3 o)
return o.getObj3Name() != null && o.getObj3Desc() != null;
ORIGINAL ANSWER
You might be able to do it by delegating the validation to each object:
List<Object1> object1List = getObject1List();
if(!object1List.stream().allMatch(Object1::isValid))
//throw error
And add an isValid
method to each object
public class Object1
private String obj1Name;
private String obj1Desc;
private List<Object2> object2List;
public boolean isValid()
return obj1Name != null
&& obj1Desc != null
&& object2List.stream().allMatch(Object2::isValid);
public class Object2
private String obj2Name;
private String obj2Desc;
private List<Object3> object3List;
public boolean isValid()
return obj2Name != null
&& obj2Desc != null
&& object3List.stream().allMatch(Object3::isValid);
public class Object3
private String obj3Name;
private String obj3Desc;
public boolean isValid()
return obj3Name != null
&& obj3Desc != null;
EDIT: An idea to externalize the check, you need to create Functional Interface
ObjectValidatorInterface ov = new ObjectValidator();
if(!object1List.stream().allMatch(o -> ov.validate(o, Object1.class)))
// throw error;
And the interface
@FunctionalInterface
interface ObjectValidatorInterface
boolean validate(Object object, Class clazz);
class ObjectValidator implements ObjectValidatorInterface
public boolean validate(Object object, Class clazz)
boolean valid = false;
if(Object1.class.getName().equals(clazz.getName()))
valid = validateObject1((Object1) object);
else if(Object2.class.getName().equals(clazz.getName()))
valid = validateObject2((Object2) object);
else if(Object3.class.getName().equals(clazz.getName()))
valid = validateObject3((Object3) object);
return valid;
private boolean validateObject1(Object1 o)
boolean valid;
valid = o.getObj1Name() != null && o.getObj1Desc() != null;
if(!(o.getObject2List() == null
private boolean validateObject2(Object2 o)
private boolean validateObject3(Object3 o)
return o.getObj3Name() != null && o.getObj3Desc() != null;
ORIGINAL ANSWER
You might be able to do it by delegating the validation to each object:
List<Object1> object1List = getObject1List();
if(!object1List.stream().allMatch(Object1::isValid))
//throw error
And add an isValid
method to each object
public class Object1
private String obj1Name;
private String obj1Desc;
private List<Object2> object2List;
public boolean isValid()
return obj1Name != null
&& obj1Desc != null
&& object2List.stream().allMatch(Object2::isValid);
public class Object2
private String obj2Name;
private String obj2Desc;
private List<Object3> object3List;
public boolean isValid()
return obj2Name != null
&& obj2Desc != null
&& object3List.stream().allMatch(Object3::isValid);
public class Object3
private String obj3Name;
private String obj3Desc;
public boolean isValid()
return obj3Name != null
&& obj3Desc != null;
edited Dec 5 at 14:20
answered Dec 5 at 13:19
Bentaye
3,77131729
3,77131729
3
I really dislike this - you put the validation conditions inside the POJO itself - is this ever a good idea? what if there are 100 of these?
– Eugene
Dec 5 at 13:24
good one, but I think theseisValid
methods should be moved out of the POJO classes
– Andrew Tobilko
Dec 5 at 13:24
@Bentaye nope, the field names are different - this would not work
– Eugene
Dec 5 at 13:27
@Eugene Added an other version where the check is done by an external object
– Bentaye
Dec 5 at 14:22
@Bentaye well that is a bit better, I agree. But now, imagine supporting that and testing it correctly, with at least 10 different validation types and rules... you might be on the verge of the next mission impossible movie, which I would not want to be part of
– Eugene
Dec 5 at 14:23
|
show 1 more comment
3
I really dislike this - you put the validation conditions inside the POJO itself - is this ever a good idea? what if there are 100 of these?
– Eugene
Dec 5 at 13:24
good one, but I think theseisValid
methods should be moved out of the POJO classes
– Andrew Tobilko
Dec 5 at 13:24
@Bentaye nope, the field names are different - this would not work
– Eugene
Dec 5 at 13:27
@Eugene Added an other version where the check is done by an external object
– Bentaye
Dec 5 at 14:22
@Bentaye well that is a bit better, I agree. But now, imagine supporting that and testing it correctly, with at least 10 different validation types and rules... you might be on the verge of the next mission impossible movie, which I would not want to be part of
– Eugene
Dec 5 at 14:23
3
3
I really dislike this - you put the validation conditions inside the POJO itself - is this ever a good idea? what if there are 100 of these?
– Eugene
Dec 5 at 13:24
I really dislike this - you put the validation conditions inside the POJO itself - is this ever a good idea? what if there are 100 of these?
– Eugene
Dec 5 at 13:24
good one, but I think these
isValid
methods should be moved out of the POJO classes– Andrew Tobilko
Dec 5 at 13:24
good one, but I think these
isValid
methods should be moved out of the POJO classes– Andrew Tobilko
Dec 5 at 13:24
@Bentaye nope, the field names are different - this would not work
– Eugene
Dec 5 at 13:27
@Bentaye nope, the field names are different - this would not work
– Eugene
Dec 5 at 13:27
@Eugene Added an other version where the check is done by an external object
– Bentaye
Dec 5 at 14:22
@Eugene Added an other version where the check is done by an external object
– Bentaye
Dec 5 at 14:22
@Bentaye well that is a bit better, I agree. But now, imagine supporting that and testing it correctly, with at least 10 different validation types and rules... you might be on the verge of the next mission impossible movie, which I would not want to be part of
– Eugene
Dec 5 at 14:23
@Bentaye well that is a bit better, I agree. But now, imagine supporting that and testing it correctly, with at least 10 different validation types and rules... you might be on the verge of the next mission impossible movie, which I would not want to be part of
– Eugene
Dec 5 at 14:23
|
show 1 more comment
up vote
1
down vote
Well, you can definitely avoid the "nesting" by using the Stream API:
if(object1List.stream()
.anyMatch(a -> a.getObj1Name() == null ||
a.getObj1Desc() == null))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObj2Name() == null ||
b.getObj2Desc() == null)))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObject3List().stream()
.anyMatch(c -> c.getObj3Name() == null ||
c.getObj3Desc() == null))))
// throw error
Another approach being more compact, but probably less efficient:
boolean result = object1List.stream()
.flatMap(a -> a.getObject2List().stream()
.flatMap(b -> b.getObject3List().stream()
.flatMap(c -> Stream.of(a.getObj1Name(),
a.getObj1Desc(), b.getObj2Name(),
b.getObj2Desc(), c.getObj3Name(), c.getObj3Desc()))))
.anyMatch(Objects::isNull);
if(result) // throw error
So, to conclude if performance is a concern then proceed with your approach or try and see if the parallel stream API can do you any good, otherwise, the above should suffice.
6
to me, it's way worse than OP's approach
– Andrew Tobilko
Dec 5 at 13:12
1
@AndrewTobilko the goal was to remove the nesting, and even in terms of efficiency that really depends on the number of elements in the source.
– Aomine
Dec 5 at 13:14
2
Yeah, flatmap that shit.
– michid
Dec 5 at 13:24
add a comment |
up vote
1
down vote
Well, you can definitely avoid the "nesting" by using the Stream API:
if(object1List.stream()
.anyMatch(a -> a.getObj1Name() == null ||
a.getObj1Desc() == null))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObj2Name() == null ||
b.getObj2Desc() == null)))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObject3List().stream()
.anyMatch(c -> c.getObj3Name() == null ||
c.getObj3Desc() == null))))
// throw error
Another approach being more compact, but probably less efficient:
boolean result = object1List.stream()
.flatMap(a -> a.getObject2List().stream()
.flatMap(b -> b.getObject3List().stream()
.flatMap(c -> Stream.of(a.getObj1Name(),
a.getObj1Desc(), b.getObj2Name(),
b.getObj2Desc(), c.getObj3Name(), c.getObj3Desc()))))
.anyMatch(Objects::isNull);
if(result) // throw error
So, to conclude if performance is a concern then proceed with your approach or try and see if the parallel stream API can do you any good, otherwise, the above should suffice.
6
to me, it's way worse than OP's approach
– Andrew Tobilko
Dec 5 at 13:12
1
@AndrewTobilko the goal was to remove the nesting, and even in terms of efficiency that really depends on the number of elements in the source.
– Aomine
Dec 5 at 13:14
2
Yeah, flatmap that shit.
– michid
Dec 5 at 13:24
add a comment |
up vote
1
down vote
up vote
1
down vote
Well, you can definitely avoid the "nesting" by using the Stream API:
if(object1List.stream()
.anyMatch(a -> a.getObj1Name() == null ||
a.getObj1Desc() == null))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObj2Name() == null ||
b.getObj2Desc() == null)))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObject3List().stream()
.anyMatch(c -> c.getObj3Name() == null ||
c.getObj3Desc() == null))))
// throw error
Another approach being more compact, but probably less efficient:
boolean result = object1List.stream()
.flatMap(a -> a.getObject2List().stream()
.flatMap(b -> b.getObject3List().stream()
.flatMap(c -> Stream.of(a.getObj1Name(),
a.getObj1Desc(), b.getObj2Name(),
b.getObj2Desc(), c.getObj3Name(), c.getObj3Desc()))))
.anyMatch(Objects::isNull);
if(result) // throw error
So, to conclude if performance is a concern then proceed with your approach or try and see if the parallel stream API can do you any good, otherwise, the above should suffice.
Well, you can definitely avoid the "nesting" by using the Stream API:
if(object1List.stream()
.anyMatch(a -> a.getObj1Name() == null ||
a.getObj1Desc() == null))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObj2Name() == null ||
b.getObj2Desc() == null)))
// throw error
else if(object1List.stream()
.anyMatch(a -> a.getObject2List().stream()
.anyMatch(b -> b.getObject3List().stream()
.anyMatch(c -> c.getObj3Name() == null ||
c.getObj3Desc() == null))))
// throw error
Another approach being more compact, but probably less efficient:
boolean result = object1List.stream()
.flatMap(a -> a.getObject2List().stream()
.flatMap(b -> b.getObject3List().stream()
.flatMap(c -> Stream.of(a.getObj1Name(),
a.getObj1Desc(), b.getObj2Name(),
b.getObj2Desc(), c.getObj3Name(), c.getObj3Desc()))))
.anyMatch(Objects::isNull);
if(result) // throw error
So, to conclude if performance is a concern then proceed with your approach or try and see if the parallel stream API can do you any good, otherwise, the above should suffice.
edited Dec 5 at 13:13
answered Dec 5 at 13:11
Aomine
36.3k62961
36.3k62961
6
to me, it's way worse than OP's approach
– Andrew Tobilko
Dec 5 at 13:12
1
@AndrewTobilko the goal was to remove the nesting, and even in terms of efficiency that really depends on the number of elements in the source.
– Aomine
Dec 5 at 13:14
2
Yeah, flatmap that shit.
– michid
Dec 5 at 13:24
add a comment |
6
to me, it's way worse than OP's approach
– Andrew Tobilko
Dec 5 at 13:12
1
@AndrewTobilko the goal was to remove the nesting, and even in terms of efficiency that really depends on the number of elements in the source.
– Aomine
Dec 5 at 13:14
2
Yeah, flatmap that shit.
– michid
Dec 5 at 13:24
6
6
to me, it's way worse than OP's approach
– Andrew Tobilko
Dec 5 at 13:12
to me, it's way worse than OP's approach
– Andrew Tobilko
Dec 5 at 13:12
1
1
@AndrewTobilko the goal was to remove the nesting, and even in terms of efficiency that really depends on the number of elements in the source.
– Aomine
Dec 5 at 13:14
@AndrewTobilko the goal was to remove the nesting, and even in terms of efficiency that really depends on the number of elements in the source.
– Aomine
Dec 5 at 13:14
2
2
Yeah, flatmap that shit.
– michid
Dec 5 at 13:24
Yeah, flatmap that shit.
– michid
Dec 5 at 13:24
add a comment |
up vote
1
down vote
A validator, as a functional interface, is a Consumer
which consumes a value of a specific type, performs checks and throws an Exception if something is off.
Traversal of the data structure (Tree) can be accomplished over streams (peek
to visit a node, flatmap
to recurse into the children). For the validation, we introduce a NO-OP map operation, which validates and returns the value, allowing the stream to continue.
BiConsumer<String, Object> checkRequired = (name, value) ->
if (value == null)
throw new IllegalArgumentException(name + " is required");
;
Consumer<Object1> obj1Validator = obj1 ->
checkRequired.accept("Object1", obj1);
checkRequired.accept("obj1Name", obj1.getObj1Name());
checkRequired.accept("obj1Desc", obj1.getObj1Desc());
;
Consumer<Object2> obj2Validator = obj2 ->
checkRequired.accept("Object2", obj2);
checkRequired.accept("obj2Name", obj2.getObj2Name());
checkRequired.accept("obj2Desc", obj2.getObj2Desc());
;
Consumer<Object3> obj3Validator = obj3 ->
checkRequired.accept("Object3", obj3);
checkRequired.accept("obj3Name", obj3.getObj3Name());
checkRequired.accept("obj3Desc", obj3.getObj3Desc());
;
Object1 obj1 = ...; // assign some value
Stream.of(obj1)
.peek(obj1Validator)
.filter(x -> x.getObject2List() != null)
.map(Object1::getObject2List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj2Validator)
.map(Object2::getObject3List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj3Validator)
.count();
now imagine supporting this for numerous rules and fields... seriously, don't.
– Eugene
Dec 5 at 13:40
@Eugene that's what validation is about - check each model and each field. Of course that validation can be delegated to a framework, such as using Bean Validation (JSR-380) which drives field validations over annotations.
– Peter Walser
Dec 5 at 13:47
would you write this code or use a framework? that was my point
– Eugene
Dec 5 at 13:48
I would certainly use a framework, in particular Bean Validation (JSR-380, beanvalidation.org/specification)
– Peter Walser
Dec 5 at 14:07
add a comment |
up vote
1
down vote
A validator, as a functional interface, is a Consumer
which consumes a value of a specific type, performs checks and throws an Exception if something is off.
Traversal of the data structure (Tree) can be accomplished over streams (peek
to visit a node, flatmap
to recurse into the children). For the validation, we introduce a NO-OP map operation, which validates and returns the value, allowing the stream to continue.
BiConsumer<String, Object> checkRequired = (name, value) ->
if (value == null)
throw new IllegalArgumentException(name + " is required");
;
Consumer<Object1> obj1Validator = obj1 ->
checkRequired.accept("Object1", obj1);
checkRequired.accept("obj1Name", obj1.getObj1Name());
checkRequired.accept("obj1Desc", obj1.getObj1Desc());
;
Consumer<Object2> obj2Validator = obj2 ->
checkRequired.accept("Object2", obj2);
checkRequired.accept("obj2Name", obj2.getObj2Name());
checkRequired.accept("obj2Desc", obj2.getObj2Desc());
;
Consumer<Object3> obj3Validator = obj3 ->
checkRequired.accept("Object3", obj3);
checkRequired.accept("obj3Name", obj3.getObj3Name());
checkRequired.accept("obj3Desc", obj3.getObj3Desc());
;
Object1 obj1 = ...; // assign some value
Stream.of(obj1)
.peek(obj1Validator)
.filter(x -> x.getObject2List() != null)
.map(Object1::getObject2List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj2Validator)
.map(Object2::getObject3List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj3Validator)
.count();
now imagine supporting this for numerous rules and fields... seriously, don't.
– Eugene
Dec 5 at 13:40
@Eugene that's what validation is about - check each model and each field. Of course that validation can be delegated to a framework, such as using Bean Validation (JSR-380) which drives field validations over annotations.
– Peter Walser
Dec 5 at 13:47
would you write this code or use a framework? that was my point
– Eugene
Dec 5 at 13:48
I would certainly use a framework, in particular Bean Validation (JSR-380, beanvalidation.org/specification)
– Peter Walser
Dec 5 at 14:07
add a comment |
up vote
1
down vote
up vote
1
down vote
A validator, as a functional interface, is a Consumer
which consumes a value of a specific type, performs checks and throws an Exception if something is off.
Traversal of the data structure (Tree) can be accomplished over streams (peek
to visit a node, flatmap
to recurse into the children). For the validation, we introduce a NO-OP map operation, which validates and returns the value, allowing the stream to continue.
BiConsumer<String, Object> checkRequired = (name, value) ->
if (value == null)
throw new IllegalArgumentException(name + " is required");
;
Consumer<Object1> obj1Validator = obj1 ->
checkRequired.accept("Object1", obj1);
checkRequired.accept("obj1Name", obj1.getObj1Name());
checkRequired.accept("obj1Desc", obj1.getObj1Desc());
;
Consumer<Object2> obj2Validator = obj2 ->
checkRequired.accept("Object2", obj2);
checkRequired.accept("obj2Name", obj2.getObj2Name());
checkRequired.accept("obj2Desc", obj2.getObj2Desc());
;
Consumer<Object3> obj3Validator = obj3 ->
checkRequired.accept("Object3", obj3);
checkRequired.accept("obj3Name", obj3.getObj3Name());
checkRequired.accept("obj3Desc", obj3.getObj3Desc());
;
Object1 obj1 = ...; // assign some value
Stream.of(obj1)
.peek(obj1Validator)
.filter(x -> x.getObject2List() != null)
.map(Object1::getObject2List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj2Validator)
.map(Object2::getObject3List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj3Validator)
.count();
A validator, as a functional interface, is a Consumer
which consumes a value of a specific type, performs checks and throws an Exception if something is off.
Traversal of the data structure (Tree) can be accomplished over streams (peek
to visit a node, flatmap
to recurse into the children). For the validation, we introduce a NO-OP map operation, which validates and returns the value, allowing the stream to continue.
BiConsumer<String, Object> checkRequired = (name, value) ->
if (value == null)
throw new IllegalArgumentException(name + " is required");
;
Consumer<Object1> obj1Validator = obj1 ->
checkRequired.accept("Object1", obj1);
checkRequired.accept("obj1Name", obj1.getObj1Name());
checkRequired.accept("obj1Desc", obj1.getObj1Desc());
;
Consumer<Object2> obj2Validator = obj2 ->
checkRequired.accept("Object2", obj2);
checkRequired.accept("obj2Name", obj2.getObj2Name());
checkRequired.accept("obj2Desc", obj2.getObj2Desc());
;
Consumer<Object3> obj3Validator = obj3 ->
checkRequired.accept("Object3", obj3);
checkRequired.accept("obj3Name", obj3.getObj3Name());
checkRequired.accept("obj3Desc", obj3.getObj3Desc());
;
Object1 obj1 = ...; // assign some value
Stream.of(obj1)
.peek(obj1Validator)
.filter(x -> x.getObject2List() != null)
.map(Object1::getObject2List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj2Validator)
.map(Object2::getObject3List)
.filter(Objects::nonNull)
.flatMap(List::stream)
.peek(obj3Validator)
.count();
edited Dec 5 at 13:43
answered Dec 5 at 13:29
Peter Walser
10.3k23455
10.3k23455
now imagine supporting this for numerous rules and fields... seriously, don't.
– Eugene
Dec 5 at 13:40
@Eugene that's what validation is about - check each model and each field. Of course that validation can be delegated to a framework, such as using Bean Validation (JSR-380) which drives field validations over annotations.
– Peter Walser
Dec 5 at 13:47
would you write this code or use a framework? that was my point
– Eugene
Dec 5 at 13:48
I would certainly use a framework, in particular Bean Validation (JSR-380, beanvalidation.org/specification)
– Peter Walser
Dec 5 at 14:07
add a comment |
now imagine supporting this for numerous rules and fields... seriously, don't.
– Eugene
Dec 5 at 13:40
@Eugene that's what validation is about - check each model and each field. Of course that validation can be delegated to a framework, such as using Bean Validation (JSR-380) which drives field validations over annotations.
– Peter Walser
Dec 5 at 13:47
would you write this code or use a framework? that was my point
– Eugene
Dec 5 at 13:48
I would certainly use a framework, in particular Bean Validation (JSR-380, beanvalidation.org/specification)
– Peter Walser
Dec 5 at 14:07
now imagine supporting this for numerous rules and fields... seriously, don't.
– Eugene
Dec 5 at 13:40
now imagine supporting this for numerous rules and fields... seriously, don't.
– Eugene
Dec 5 at 13:40
@Eugene that's what validation is about - check each model and each field. Of course that validation can be delegated to a framework, such as using Bean Validation (JSR-380) which drives field validations over annotations.
– Peter Walser
Dec 5 at 13:47
@Eugene that's what validation is about - check each model and each field. Of course that validation can be delegated to a framework, such as using Bean Validation (JSR-380) which drives field validations over annotations.
– Peter Walser
Dec 5 at 13:47
would you write this code or use a framework? that was my point
– Eugene
Dec 5 at 13:48
would you write this code or use a framework? that was my point
– Eugene
Dec 5 at 13:48
I would certainly use a framework, in particular Bean Validation (JSR-380, beanvalidation.org/specification)
– Peter Walser
Dec 5 at 14:07
I would certainly use a framework, in particular Bean Validation (JSR-380, beanvalidation.org/specification)
– Peter Walser
Dec 5 at 14:07
add a comment |
up vote
0
down vote
Well, you could use a function/loop which sifts through an object(The generic Object). That way, you won't have to run a separate for loop for each object if the name of the member variable "desc" is uniform in all the three objects. But that's another level of nesting so not sure you'd want to use that if you're just looking to avoid nesting.
add a comment |
up vote
0
down vote
Well, you could use a function/loop which sifts through an object(The generic Object). That way, you won't have to run a separate for loop for each object if the name of the member variable "desc" is uniform in all the three objects. But that's another level of nesting so not sure you'd want to use that if you're just looking to avoid nesting.
add a comment |
up vote
0
down vote
up vote
0
down vote
Well, you could use a function/loop which sifts through an object(The generic Object). That way, you won't have to run a separate for loop for each object if the name of the member variable "desc" is uniform in all the three objects. But that's another level of nesting so not sure you'd want to use that if you're just looking to avoid nesting.
Well, you could use a function/loop which sifts through an object(The generic Object). That way, you won't have to run a separate for loop for each object if the name of the member variable "desc" is uniform in all the three objects. But that's another level of nesting so not sure you'd want to use that if you're just looking to avoid nesting.
answered Dec 5 at 13:20
benignfoppery
394
394
add a comment |
add a comment |
up vote
0
down vote
If their validation seems to be the same, only the type change, then use interface have Object1
, Object2
and Object3
implements ICommon
:
interface ICommon
String getField1();
int getField2();
Iterable<? extends ICommon> getChildren();
Then have this:
private void validate0(String prefix, ICommon common)
if (common.getField1() == null) throw new ValidationException(prefix + ".field1 can't be null");
if (common.getField2() == null) throw new ValidationException(prefix + ".field2 can't be null");
int index = 0;
for (ICommon child : getChildren())
validate0(prefix + ".children[" + index + "]", child);
++index;
public void validate(ICommon common)
validate0("common", common);
You may also invert this using a BiConsumer<String, ICommon>
(or Consumer<ICommon>
) to validate if you don't care about proper error reporting).
- This will also make it clearer about which validation may apply on your object
- Using stream does not (always) make it clearer (see Peter Walser answer and try to understand the big stream :)).
add a comment |
up vote
0
down vote
If their validation seems to be the same, only the type change, then use interface have Object1
, Object2
and Object3
implements ICommon
:
interface ICommon
String getField1();
int getField2();
Iterable<? extends ICommon> getChildren();
Then have this:
private void validate0(String prefix, ICommon common)
if (common.getField1() == null) throw new ValidationException(prefix + ".field1 can't be null");
if (common.getField2() == null) throw new ValidationException(prefix + ".field2 can't be null");
int index = 0;
for (ICommon child : getChildren())
validate0(prefix + ".children[" + index + "]", child);
++index;
public void validate(ICommon common)
validate0("common", common);
You may also invert this using a BiConsumer<String, ICommon>
(or Consumer<ICommon>
) to validate if you don't care about proper error reporting).
- This will also make it clearer about which validation may apply on your object
- Using stream does not (always) make it clearer (see Peter Walser answer and try to understand the big stream :)).
add a comment |
up vote
0
down vote
up vote
0
down vote
If their validation seems to be the same, only the type change, then use interface have Object1
, Object2
and Object3
implements ICommon
:
interface ICommon
String getField1();
int getField2();
Iterable<? extends ICommon> getChildren();
Then have this:
private void validate0(String prefix, ICommon common)
if (common.getField1() == null) throw new ValidationException(prefix + ".field1 can't be null");
if (common.getField2() == null) throw new ValidationException(prefix + ".field2 can't be null");
int index = 0;
for (ICommon child : getChildren())
validate0(prefix + ".children[" + index + "]", child);
++index;
public void validate(ICommon common)
validate0("common", common);
You may also invert this using a BiConsumer<String, ICommon>
(or Consumer<ICommon>
) to validate if you don't care about proper error reporting).
- This will also make it clearer about which validation may apply on your object
- Using stream does not (always) make it clearer (see Peter Walser answer and try to understand the big stream :)).
If their validation seems to be the same, only the type change, then use interface have Object1
, Object2
and Object3
implements ICommon
:
interface ICommon
String getField1();
int getField2();
Iterable<? extends ICommon> getChildren();
Then have this:
private void validate0(String prefix, ICommon common)
if (common.getField1() == null) throw new ValidationException(prefix + ".field1 can't be null");
if (common.getField2() == null) throw new ValidationException(prefix + ".field2 can't be null");
int index = 0;
for (ICommon child : getChildren())
validate0(prefix + ".children[" + index + "]", child);
++index;
public void validate(ICommon common)
validate0("common", common);
You may also invert this using a BiConsumer<String, ICommon>
(or Consumer<ICommon>
) to validate if you don't care about proper error reporting).
- This will also make it clearer about which validation may apply on your object
- Using stream does not (always) make it clearer (see Peter Walser answer and try to understand the big stream :)).
answered Dec 5 at 14:08
NoDataFound
5,5621740
5,5621740
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53632516%2fjava-8-alternative-for-validating-data-inside-multiple-nested-loops%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
7
are you throwing the same error on each condition ? if so, what type of error?
– Aomine
Dec 5 at 12:42
yes, throwing same error on each condition, the error will be
InvalidParameterException
– hades
Dec 5 at 13:10
You might find useful docs.spring.io/spring-framework/docs/current/javadoc-api/org/…
– Federico Piazza
Dec 5 at 13:22
3
don't get me wrong but have you considered a framework with support for
@NotNull
?– Eugene
Dec 5 at 13:28
@Eugene Exactly what I wanted to point out as well. I mean that's what something like
javax.validation.constraints
are meant for.– nullpointer
Dec 5 at 13:33