I have to assign the result of an operation (a db query or a computation) to a return variable, and eventually perform another operation if the result is not valid (null, empty, ...); however, this pattern happen at least a couple of time, and it seems a code smell to me. Should I refactor it in any way?
String result = planA();
if(!isValid(result))
result = planB();
if(!isValid(result))
result = planC();
if(!isValid(result))
result = planD();
return result;
You could factor out that as a function that returns the first valid result since that is that you actually do.
In fact, in terms of expected behavior, your current code could be written like :
String result = planA();
if(isValid(result))
return planB();
if(isValid(result))
return planC();
if(isValid(result))
return planD();
return result;
You can factor out that with a function :
public String computeResult(Supplier<String>... functions){
String result = null;
for (Supplier<String> function : functions){
result = function.get();
if (isValid(result)){
return result;
}
}
return result;
}
And call that :
computeResult(this::planA, this::planB, this::planC, this::planD, ()-> this.planE(anyParam));
As alternative you could replace the loop by a stream in the function :
public String computeResult(Supplier<String>... functions){
return
Arrays.stream(functions)
.filter(s-> isValid(s.get()))
.findFirst()
.orElse(functions.get(function.length-1));
// if no valid return the last result function as in the initial code
}
If I understand it correctly, planD is the default case if all previous checks failed. I would write it like this
return Stream.of(planA(),planB(),planC())
.dropWhile(s->!isValid(s))
.findFirst()
.orElse(planD());
I would implement a util class that can be used by anyone for any purpose:
public static <T> T computeWithFallbacks(Predicate<T> validityPredicate, Supplier<T>... suppliers) {
T result = null;
for (Supplier<T> supplier : suppliers) {
result = supplier.get();
if (validityPredicate.test(result)) {
return result;
}
}
return result;
}
This way you can provide the validity check predicate and a varargs of value suppliers that will be computed in the given order
Related
I'm trying to make something like this:
private String getStringIfObjectIsPresent(Optional<Object> object){
object.ifPresent(() ->{
String result = "result";
//some logic with result and return it
return result;
}).orElseThrow(MyCustomException::new);
}
This won't work, because ifPresent takes Consumer functional interface as parameter, which has void accept(T t). It cannot return any value. Is there any other way to do it ?
Actually what you are searching is: Optional.map. Your code would then look like:
object.map(o -> "result" /* or your function */)
.orElseThrow(MyCustomException::new);
I would rather omit passing the Optional if you can. In the end you gain nothing using an Optional here. A slightly other variant:
public String getString(Object yourObject) {
if (Objects.isNull(yourObject)) { // or use requireNonNull instead if NullPointerException suffices
throw new MyCustomException();
}
String result = ...
// your string mapping function
return result;
}
If you already have the Optional-object due to another call, I would still recommend you to use the map-method, instead of isPresent, etc. for the single reason, that I find it more readable (clearly a subjective decision ;-)).
Two options here:
Replace ifPresent with map and use Function instead of Consumer
private String getStringIfObjectIsPresent(Optional<Object> object) {
return object
.map(obj -> {
String result = "result";
//some logic with result and return it
return result;
})
.orElseThrow(MyCustomException::new);
}
Use isPresent:
private String getStringIfObjectIsPresent(Optional<Object> object) {
if (object.isPresent()) {
String result = "result";
//some logic with result and return it
return result;
} else {
throw new MyCustomException();
}
}
Use the map-function instead. It transforms the value inside the optional.
Like this:
private String getStringIfObjectIsPresent(Optional<Object> object) {
return object.map(() -> {
String result = "result";
//some logic with result and return it
return result;
}).orElseThrow(MyCustomException::new);
}
I'd prefer mapping after making sure the value is available
private String getStringIfObjectIsPresent(Optional<Object> object) {
Object ob = object.orElseThrow(MyCustomException::new);
// do your mapping with ob
String result = your-map-function(ob);
return result;
}
or one liner
private String getStringIfObjectIsPresent(Optional<Object> object) {
return your-map-function(object.orElseThrow(MyCustomException::new));
}
The example u put is not a good example. Optional shouldn't be sent as parameter into another function. Good practice is always sending non-null parameter into function. So that we know always that the input will not be null. This can decrease our code uncertainty.
I wrote a piece of code and wonder how I can write it more elegant, using streams
here it is:
public boolean possibleToAddTask(LocalDate taskDate, final String username) {
List<Task> userTasklist = find(username).getTaskList();
for(Task task : userTasklist) {
if(task.getDate().equals(taskDate)){
return false;
}
}
return true;
}
Here - some boolean is returned from a method. If specified date already exists in some task it returns false, otherwise true (so the return type answers the question raised in method's name :))
I was trying with filters on streams, but It worked just for a while, and then unit tests gave me some unexpected results so I deleted it and wrote it like Its upper. Now I want to beautify it
previously it was like this:
public boolean possibleToAddTask(LocalDate taskDate, final String username) {
List<Task> userTasklist = find(username).getTaskList();
try {
userTasklist.stream().filter(n -> n.getDate().equals(taskDate)).findFirst().get();
return true;
} catch (NoSuchElementException e) {
return false;
}
}
thanks in advance :)
Method findFirst() return an Optional. So you can just check if optional is empty.
return !userTasklist.stream()
.filter(n -> n.getDate().equals(taskDate))
.findFirst().isPresent();
Or even easier approach.
return !userTasklist.stream().anyMatch(n -> n.getDate().equals(taskDate));
EDIT: Now unit tests should pass.
How about doing something lik transforming the List into Set and then calling contains():
return userTasklist.stream().map(Task::getDate).collect(Collectors.toSet()).contains(taskDate);
Is it possible to wrap following code in a reusable function?
EDIT: this is just an example, I want a working solution for ALL recursion depths
what I want is that following code is generated:
if (MyObject o == null ||
o.getSubObject() == null ||
o..getSubObject().getSubSubObject() == null /*||
... */)
return defaultValue;
return o.getSubObject().getSubObject()/*...*/.getDesiredValue();
by calling something like
Object defaultValue = null;
Object result = NullSafeCall(o.getSubObject().getSubObject()/*...*/.getDesiredValue(), defaultValue);
The seond code block is just an idea, I don't care how it looks like, all I want is that I, if desired, can avoid all the null checks before calling a deeper function...
Injection could do this propably, but is there no other/easier solution? Never looked at injection before yet...
EDIT2: example in another language: http://groovy.codehaus.org/Operators#Operators-SafeNavigationOperator
Not really, any code you would write this way would look horrible and/or use very slow reflection. Unless you use an actual Java preprocessor that can understand and change the code you've written.
A better (but associated with quite a bit of refactoring) approach would be to make sure that the values in question cannot possibly be null. For example, you could modify the individual accessors (getSubObject(), getDesiredValue()) to never return null in the first place: make them return default values. The accessors on the default values return default values in turn.
Java8 helps to get the closest you'll get to your syntax with decent performance I suspect;
// Evaluate with default 5 if anything returns null.
int result = Optional.eval(5, o, x->x.getSubObject(), x->x.getDesiredValue());
This can be done with this utility class;
class Optional {
public static <T, Tdef, T1> Tdef eval(Tdef def, T input, Function<T,T1> fn1,
Function<T1, Tdef> fn2)
{
if(input == null) return def;
T1 res1 = fn1.apply(input);
if(res1 == null) return def;
return fn2.apply(res1);
}
}
Sadly, you'll need a separate eval() defined per number of method calls in the chain, so you may want to define a few, but compile time type safe and reusable with just about any calls/types.
You can do something like this
public static Object NullSafeCall(MyObject o,Object defaultValue){
if ( o == null || o.getSubObject() == null)
{
return defaultValue;
}
else
{
return o.getSubObject().getDesiredValue();
}
}
Now you can call this method as follows
Object result = NullSafeCall(o, defaultValue);
i would suggest just replace
Object result = NullSafeCall(o.getSubObject().getDesiredValue(), defaultValue);
by the
Object result = (o == null || o.subObject == null) ? defaultVlue : o.getSubObject().getDesiredValue();
Create method only if you can reuse it......
What you want is not possible. It is essential to understand that using this syntax: Object result = NullSafeCall(o.getSubObject().getSubObject() ...); the part of o.getSubObject().getSubObject() will be evaluated before any control passes to the function/method thus throwing the exception.
It is required to have some type of context before executing such code. The closest to this I could think of, can be done using anonymous inner classes like the example below:
// intended to be implemented by an anonymous inner class
interface NullSafeOperation<T> {
public T executeSafely();
};
// our executor that executes operations safely
public static class NullSafeExecutor<T> {
public NullSafeExecutor() {}
public T execute(T defaultValue, NullSafeOperation<T> nso) {
T result = defaultValue;
try {
result = nso.executeSafely();
} catch(NullPointerException e) {
// ignore
}
return result;
}
// utility method to create a new instance and execute in one step
public static <T> T executeOperation(T defaultValue, NullSafeOperation<T> nso) {
NullSafeExecutor<T> e = new NullSafeExecutor<T>();
T result = e.execute(defaultValue, nso);
return result;
}
}
public static void main(String[] args) {
final String aNullString = null;
String result = NullSafeExecutor.executeOperation("MyDefault", new NullSafeOperation<String>() {
#Override
public String executeSafely() {
// trying to call a method on a null string
// it will throw NullPointerException but it will be catched by the executor
return aNullString.trim();
}
});
System.out.println("Output = " + result); // prints: Output = MyDefault
}
Am currently trying to sort my object by lastname first then first name then date of birth then ssn. But logically I can only come up with is the lastname then the firstname
any tips?
public int compareTo(Doctor o)
{
int result = this.lastName.compareTo(o.lastName());
return result == 0 ?this.firstName.compareTo(((Doctor) o).firstName()):result;
}
Nested if would be better choice to implement this.
public int compareTo(Doctor o){
int result = this.lastName.compareTo(o.lastName());
if(result==0){
result = this.firstName.compareTo(o.firstName());
if(result==0){
result = this.dob.compareTo(o.dob());
if(result==0){
....
}
}
}
return result;
}
You can use the following:
public int compareTo(Doctor o)
{
int result = this.lastName.compareTo(o.lastName());
if (result != 0)
return result;
result = this.firstName.compareTo(o.firstName());
if (result != 0)
return result;
result = this.birthDate.compareTo(o.birthDate());
if (result != 0)
return result;
return this.ssn.compareTo(o.ssn());
}
First sort on lastname. If the sort value is 0, sort on firstname. If that result is 0, sort for date of birth, and so on. You'll have multiple return statements, sure, but it's a lot more readable.
As you probably know, a result value of 0 means the two values are equal. In your use case, this should result in an additional sort instead of simply returning the values.
Edit: other answers below have provided exact implementation for this.
As you may have realized, this is a kind of the "chain of responsibility". So i would suggest you the pattern for this case. Chain-of-responsibility Pattern
It will save you from writing too many if()...s
I have an insertOrUpdate method which inserts an Entity when it doesn't exist or update it if it does. To enable this, I have to findByIdAndForeignKey, if it returned null insert if not then update. The problem is how do I check if it exists? So I tried getSingleResult. But it throws an exception if the
public Profile findByUserNameAndPropertyName(String userName, String propertyName) {
String namedQuery = Profile.class.getSimpleName() + ".findByUserNameAndPropertyName";
Query query = entityManager.createNamedQuery(namedQuery);
query.setParameter("name", userName);
query.setParameter("propName", propertyName);
Object result = query.getSingleResult();
if (result == null) return null;
return (Profile) result;
}
but getSingleResult throws an Exception.
Thanks
Throwing an exception is how getSingleResult() indicates it can't be found. Personally I can't stand this kind of API. It forces spurious exception handling for no real benefit. You just have to wrap the code in a try-catch block.
Alternatively you can query for a list and see if its empty. That doesn't throw an exception. Actually since you're not doing a primary key lookup technically there could be multiple results (even if one, both or the combination of your foreign keys or constraints makes this impossible in practice) so this is probably the more appropriate solution.
Try this in Java 8:
Optional first = query.getResultList().stream().findFirst();
I encapsulated the logic in the following helper method.
public class JpaResultHelper {
public static Object getSingleResultOrNull(Query query){
List results = query.getResultList();
if (results.isEmpty()) return null;
else if (results.size() == 1) return results.get(0);
throw new NonUniqueResultException();
}
}
Here's a good option for doing this:
public static <T> T getSingleResult(TypedQuery<T> query) {
query.setMaxResults(1);
List<T> list = query.getResultList();
if (list == null || list.isEmpty()) {
return null;
}
return list.get(0);
}
I've done (in Java 8):
query.getResultList().stream().findFirst().orElse(null);
From JPA 2.2, instead of .getResultList() and checking if list is empty or creating a stream you can return stream and take first element.
.getResultStream()
.findFirst()
.orElse(null);
Spring has a utility method for this:
TypedQuery<Profile> query = em.createNamedQuery(namedQuery, Profile.class);
...
return org.springframework.dao.support.DataAccessUtils.singleResult(query.getResultList());
If you wish to use the try/catch mechanism to handle this problem.. then it can be used to act like if/else. I used the try/catch to add a new record when I didn't find an existing one.
try { //if part
record = query.getSingleResult();
//use the record from the fetched result.
}
catch(NoResultException e){ //else part
//create a new record.
record = new Record();
//.........
entityManager.persist(record);
}
Here's a typed/generics version, based on Rodrigo IronMan's implementation:
public static <T> T getSingleResultOrNull(TypedQuery<T> query) {
query.setMaxResults(1);
List<T> list = query.getResultList();
if (list.isEmpty()) {
return null;
}
return list.get(0);
}
There is an alternative which I would recommend:
Query query = em.createQuery("your query");
List<Element> elementList = query.getResultList();
return CollectionUtils.isEmpty(elementList ) ? null : elementList.get(0);
This safeguards against Null Pointer Exception, guarantees only 1 result is returned.
So don't do that!
You have two options:
Run a selection to obtain the COUNT of your result set, and only pull in the data if this count is non-zero; or
Use the other kind of query (that gets a result set) and check if it has 0 or more results. It should have 1, so pull that out of your result collection and you're done.
I'd go with the second suggestion, in agreement with Cletus. It gives better performance than (potentially) 2 queries. Also less work.
Combining the useful bits of the existing answers (limiting the number of results, checking that the result is unique) and using the estabilshed method name (Hibernate), we get:
/**
* Return a single instance that matches the query, or null if the query returns no results.
*
* #param query query (required)
* #param <T> result record type
* #return record or null
*/
public static <T> T uniqueResult(#NotNull TypedQuery<T> query) {
List<T> results = query.setMaxResults(2).getResultList();
if (results.size() > 1) throw new NonUniqueResultException();
return results.isEmpty() ? null : results.get(0);
}
The undocumented method uniqueResultOptional in org.hibernate.query.Query should do the trick. Instead of having to catch a NoResultException you can just call query.uniqueResultOptional().orElse(null).
I solved this by using List<?> myList = query.getResultList(); and checking if myList.size() equals to zero.
Look this code :
return query.getResultList().stream().findFirst().orElse(null);
When findFirst() is called maybe can be throwed a NullPointerException.
the best aproach is:
return query.getResultList().stream().filter(Objects::nonNull).findFirst().orElse(null);
Here's the same logic as others suggested (get the resultList, return its only element or null), using Google Guava and a TypedQuery.
public static <T> getSingleResultOrNull(final TypedQuery<T> query) {
return Iterables.getOnlyElement(query.getResultList(), null);
}
Note that Guava will return the unintuitive IllegalArgumentException if the result set has more than one result. (The exception makes sense to clients of getOnlyElement(), as it takes the result list as its argument, but is less understandable to clients of getSingleResultOrNull().)
Here's another extension, this time in Scala.
customerQuery.getSingleOrNone match {
case Some(c) => // ...
case None => // ...
}
With this pimp:
import javax.persistence.{NonUniqueResultException, TypedQuery}
import scala.collection.JavaConversions._
object Implicits {
class RichTypedQuery[T](q: TypedQuery[T]) {
def getSingleOrNone : Option[T] = {
val results = q.setMaxResults(2).getResultList
if (results.isEmpty)
None
else if (results.size == 1)
Some(results.head)
else
throw new NonUniqueResultException()
}
}
implicit def query2RichQuery[T](q: TypedQuery[T]) = new RichTypedQuery[T](q)
}
So all of the "try to rewrite without an exception" solution in this page has a minor problem. Either its not throwing NonUnique exception, nor throw it in some wrong cases too (see below).
I think the proper solution is (maybe) this:
public static <L> L getSingleResultOrNull(TypedQuery<L> query) {
List<L> results = query.getResultList();
L foundEntity = null;
if(!results.isEmpty()) {
foundEntity = results.get(0);
}
if(results.size() > 1) {
for(L result : results) {
if(result != foundEntity) {
throw new NonUniqueResultException();
}
}
}
return foundEntity;
}
Its returning with null if there is 0 element in the list, returning nonunique if there are different elements in the list, but not returning nonunique when one of your select is not properly designed and returns the same object more then one times.
Feel free to comment.
I achieved this by getting a result list then checking if it is empty
public boolean exist(String value) {
List<Object> options = getEntityManager().createNamedQuery("AppUsers.findByEmail").setParameter('email', value).getResultList();
return !options.isEmpty();
}
It is so annoying that getSingleResult() throws exceptions
Throws:
NoResultException - if there is no result
NonUniqueResultException - if more than one result
and some other exception that you can get more info on from their documentation
I prefer #Serafins answer if you can use the new JPA features, but this is one fairly straight forward way to do it which I'm surprised hasn't been mentioned here before:
try {
return (Profile) query.getSingleResult();
} catch (NoResultException ignore) {
return null;
}
`public Example validate(String param1) {
// TODO Auto-generated method stub
Example example = new Example();
Query query =null;
Object[] myResult =null;
try {
query = sessionFactory.getCurrentSession()
.createQuery("select column from table where
column=:p_param1");
query.setParameter("p_param1",param1);
}
myResult = (Object[])query.getSingleResult();//As your problem occurs here where the query has no records it is throwing an exception
String obj1 = (String) myResult[0];
String obj2 = (String) myResult[1];
example.setobj1(ISSUtil.convertNullToSpace(obj1))
example.setobj2(ISSUtil.convertNullToSpace(obj2));
return example;
}catch(Exception e) {
e.printStackTrace();
example.setobj1(ISSUtil.convertNullToSpace(""));//setting
objects to "" in exception block
example.setobj1(ISSUtil.convertNullToSpace(""));
}
return example;
}`
Answer : Obviously when there is no records getsingleresult will throw an exception i have handled it by setting the objects to "" in the exception block even though it enter the exception you JSON object will set to ""/empty
Hope this is not a perfect answer but it might help
If some needs to modify my code more precisely and correct me always welcome.
Thats works to me:
Optional<Object> opt = Optional.ofNullable(nativeQuery.getSingleResult());
return opt.isPresent() ? opt.get() : null;