Best Practice in handling comparator - java

How to handle null objects, which comes in compareTo method. This always causes nullpointer exception. What a is best way to solve this issue.

public int compareTo(Object to) {
if (to == null) return Integer.MIN_VALUE;
// Now knowing it's not null, continue as before
}

You can check the object before you call "compareTo" method.
like this:
if(obj != null){
//TODO
}

From the fine documentation on Comparable:
Note that null is not an instance of any class, and e.compareTo(null) should throw a NullPointerException even though e.equals(null) returns false.
Don't put null in a sorted collection if you don't want to handle NullPointerExceptions.

Related

Java ArrayList contains method

#Override
public boolean contains(Object object) {
if (object != null) {
for (E element : a) {
if (object.equals(element)) {
return true;
}
}
} else {
for (E element : a) {
if (element == null) {
return true;
}
}
}
return false;
}
I am learning java and I am looking into the source code to find out how certain methods are being written. I would like to ask why is there a need to write
else {
for (E element : a) {
if (element == null) {
return true;
}
}
}
Thank you
Yes there is.
If object is null, object.equals(element) will throw a NullPointerException
So the case where object is null is handled in a separate loop.
Input argument can be null or not null.
If it's null then we need to iterate through all list elements and return true if there is null in the array.
And we have to use == operator, because equals will throw NullPointerException.
I would like to ask why is there a need to write
else {
[...]
Because otherwise, the method would always return false in the event that the condition of the if statement (object != null) is not satisfied, but that is inconsistent with the method's contract / documentation. Many Java List implementation can contain the value null as an element, and when they do, contains(null) must return true for them.
That is handled in a separate branch because when object is null, any attempt to invoke a method on it, such as equals() will cause a NullPointerException to be thrown. The approach in the if block therefore cannot be applied in that case.
List is a collection that allows insertion of null referenced objects into it.
the algorithm meant to tell you that if you have at least null in the list and you ask/search a null object later then it will return true at the 1st match....
because .equals() comparison method cannot be invoked on null and if you would invoke then null.equals(SOMETHING); will throw a NullPointerException. So here old traditional way comes to the rescue! use == comparison operator.
Many methods in Collections Framework interfaces are defined in terms of the equals method. For example, the specification for the contains(Object o) method says: "returns true if and only if this collection contains at least one element e such that (o==null ? e==null : o.equals(e))." This specification should not be construed to imply that invoking Collection.contains with a non-null argument o will cause o.equals(e) to be invoked for any element e. Implementations are free to implement optimizations whereby the equals invocation is avoided, for example, by first comparing the hash codes of the two elements. (The Object.hashCode() specification guarantees that two objects with unequal hash codes cannot be equal.) More generally, implementations of the various Collections Framework interfaces are free to take advantage of the specified behavior of underlying Object methods wherever the implementor deems it appropriate.
Refer:https://docs.oracle.com/javase/7/docs/api/java/util/Collection.html
There is a need to write else { ... because the if condition holds true only if the arg 'object' is not null.
In this case your contains() method implemented to check if object value is null or not, if it is null return true otherwise false. Implementing this method give you a opportunity to check any object(passing object as a parameter) value(using if condition or any other condition). Later on when you want to check values is there or not if it is have value you can do manipulation on object.
In ArrayList contains():
The ArrayList.contains(Object) method returns true if this list contains the specified element.
ArrayList<Integer> listObj = new ArrayList<Integer>();
listObj.add(1);
listObj.add(2);
System.out.println("Contains : "+listObj.contains(1));
This method more important check element and do somework if it is true. As a example,
if(listObj.contains(2)){
int index=arrlist.indexOf(2);
listObj.remove(index);
}
What is happening here is that the value(object) pass as the parameter is not a null value,
public boolean contains(Object object) {
if (object != null) {
then go through the ArrayList element,
for (E element : a) {
is equal to pass value,
if (object.equals(element)) {
return true
Otherwise(if object is null) go with the else block.
Throws:
ClassCastException - if the type of the specified element is incompatible with this list.
NullPointerException - if the specified element is null and this list does not permit null elements.
read more
Let's say object is a String:
This contains() method also in String class. Little bit different scenario but concept is same.
when you wish to check if one String contains a specific substring.
String word= "Hey there how are you";
if(word.contains("you")){
System.out.println("I am fine!");
}

java.util.Objects.isNull vs object == null

As you know, java.util.Objects is
This class consists of static utility methods for operating on objects.
One of such methods is Objects.isNull().
My understanding is that Objects.isNull() would remove the chance of accidentally assigning a null value to object by omitting the second =.
However, the API Note states:
This method exists to be used as a Predicate, filter(Objects::isNull)
Would there be any reason/circumstance for which I should use object == null over Objects.isNull() in an if statement?
Should Objects.isNull() be confined to Predicates exclusively?
should use object == null over Objects.isNull() in a if statement?
If you look at the source code of IsNull method,
/* Returns true if the provided reference is null otherwise returns false.*/
public static boolean isNull(Object obj) {
return obj == null;
}
It is the same. There is no difference. So you can use it safely.
Objects.isNull is intended for use within Java 8 lambda filtering.
It's much easier and clearer to write:
.stream().filter(Objects::isNull)
than to write:
.stream().filter(x -> x == null).
Within an if statement, however, either will work. The use of == null is probably easier to read but in the end it will boil down to a style preference.
Look at the source:
public static boolean isNull(Object obj) {
return obj == null;
}
To check for null values, you can use:
Objects.isNull(myObject)
null == myObject // avoids assigning by typo
myObject == null // risk of typo
The fact that Objects.isNull is meant for Predicates does not prevent you from using it as above.
Would there be any reason/circumstance for which I should use object == null over Objects.isNull() in a if statement?
Yes, one reason is to keep the code simple. Within if statement object == null is clear and well known. It can not lead to any misbehavior if for example there is a typo.
My understanding is that Objects.isNull() would remove the chance of accidentally assigning a null value to object by omitting the second =.
If there is an if (object = null) {} with omitted = it will not compile or it will generate warning in case of Boolean object! Actually there is no reason to use Objects.isNull(object) over object == null within if statement. Here are the two variants side by side:
if (object == null) {
}
if (Objects.isNull(object)) {
}
Should Objects.isNull() be confined to Predicates exclusively?
It could be said yes, it is confined to Predicates exclusively, although there is no technical hurdle to use the Objects.isNull() everywhere.
From the public static boolean isNull(Object obj) method's javadoc:
#apiNoteThis method exists to be used as a java.util.function.Predicate, filter(Objects::isNull)
So if you use the method as not a predicate you are actually using a more complex and cumbersome expression compared to the simple object == null.
Here is a snippet to compare the benefit of Objects.isNull(object)
List<String> list = Arrays.asList("a", "b", null, "c", null);
// As ready-made predicate
long countNullsWithPredicate = list.stream().filter(Objects::isNull).count();
// Lambda
long countNullsWithLambda = list.stream().filter(object -> object == null).count();
// Reimplement the Objects::isNull predicate
long countNullsWithAnonymous = list.stream().filter(new Predicate<Object>() {
#Override
public boolean test(Object obj) {
return obj == null;
}
}).count();
Semantically there is no difference but for readability I prefer the following over whatever == null:
import static java.util.Objects.isNull;
// Other stuff...
if(isNull(whatever)) {
}

what must be hashcode of null objects in Java?

According to a comment from this post, hascode of null objects can throw NPE or a value of zero. This is implementation specific. but within the same implementation, why does
Objects.hashcode and hascode(instance) return different values. for ex:
public class EqualsTesting {
public static void main(String[] args){
String p1 =null;
String p2 = null;
System.out.println(Objects.hashCode(p1));
System.out.println(p2.hashCode());
}
}
Output:
0
Exception in thread "main" java.lang.NullPointerException
at BinaryTrees.EqualsTesting.main(EqualsTesting.java:14)
If this is the case, will this not affect the key look-up in HashMap where null Key-value pairs are allowed. (It might either hash to bucket 0 or throw a NPE)
How would you calculate hashCode of an object that doesn't even exists? When p2 is null, invoking any method on it will throw a NPE. That isn't giving you any particular value of a hashCode.
Objects.hashCode() is just a wrapper method, which performs a pre-check for null values, and for reference that is not null, it returns the same value as p2.hashCode() as in this case. Here's the source code of the method:
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}
If you will search around, you'll notice that HashMap has a special handling for null keys. null values are fine as you don't compute hash code for them in a HashMap. This is the reason why null keys work fine in HashMap. As to why Objects.hashCode works fine, take a look at Rohit's answer.
As the javadoc says:
Objects.hashCode(Object o)
Returns the hash code of a non-null argument and 0 for a null
argument.
p2.hashCode() throws a NullPointerException because you are trying to access a method of a null object.
According to a comment from this post, hascode of null objects can throw NPE or a value of zero.
That is not true. (And it is not what #Bohemian's comment is saying!)
What happens in HashMap and HashSet is that they treat null as a special case. Instead of calling hashcode() on the null object (which would NPE!!), they use zero in as a hard-coded alternative hashcode.
I stress ... this is special case behaviour of HashMap and HashSet ... not hashcode().
As your example shows, if you do attempt to call the hashcode() method on null, you will get an NPE. The JLS says that that is what will happen ... and it happens whenever you try to invoke any instance method on null.
(On the other hand, the Objects.hashCode(obj) method does deal with the case where obj is null as a special case. And that's the whole point of the static method!)
The hash code of null is 0 (see Objects.hash())
public static int hashCode(Object a[]) {
if (a == null)
return 0;
int result = 1;
for (Object element : a)
result = 31 * result + (element == null ? 0 : element.hashCode());
return result;
}
0 is hard coded value for null in Hashmap. You can see the following actual implementations done in HashMap and Objects java classes.
from HashMap.java
static final int hash(Object key) {
int h;
return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
from Object.java
public static int hashCode(Object o) {
return o != null ? o.hashCode() : 0;
}

Does java.util.List.isEmpty() check if the list itself is null? [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 5 years ago.
Does java.util.List.isEmpty() check if the list itself is null, or do I have to do this check myself?
For example:
List<String> test = null;
if (!test.isEmpty()) {
for (String o : test) {
// do stuff here
}
}
Will this throw a NullPointerException because test is null?
You're trying to call the isEmpty() method on a null reference (as List test = null;). This will surely throw a NullPointerException. You should do if(test!=null) instead (checking for null first).
The method isEmpty() returns true, if an ArrayList object contains no elements; false otherwise (for that the List must first be instantiated that is in your case is null).
You may want to see this question.
I would recommend using Apache Commons Collections:
https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/CollectionUtils.html#isEmpty-java.util.Collection-
which implements it quite ok and well documented:
/**
* Null-safe check if the specified collection is empty.
* <p>
* Null returns true.
*
* #param coll the collection to check, may be null
* #return true if empty or null
* #since Commons Collections 3.2
*/
public static boolean isEmpty(Collection coll) {
return (coll == null || coll.isEmpty());
}
No, java.util.List.isEmpty() doesn't check if a list is null.
If you are using the Spring framework you can use the CollectionUtils class to check if a list is empty or not. It also takes care of the null references. Following is the code snippet from Spring framework's CollectionUtils class.
public static boolean isEmpty(Collection<?> collection) {
return (collection == null || collection.isEmpty());
}
Even if you are not using Spring, you can go on and tweak this code to add in your AppUtil class.
This will throw a NullPointerException - as will any attempt to invoke an instance method on a null reference - but in cases like this you should make an explicit check against null:
if ((test != null) && !test.isEmpty())
This is much better, and clearer, than propagating an Exception.
Invoking any method on any null reference will always result in an exception. Test if the object is null first:
List<Object> test = null;
if (test != null && !test.isEmpty()) {
// ...
}
Alternatively, write a method to encapsulate this logic:
public static <T> boolean IsNullOrEmpty(Collection<T> list) {
return list == null || list.isEmpty();
}
Then you can do:
List<Object> test = null;
if (!IsNullOrEmpty(test)) {
// ...
}
In addition to Lion's answer, I can say that you better use if(CollectionUtils.isNotEmpty(test)){...}.
This also checks for null, so a manual check is not needed.
Yes, it will throw an Exception. Maybe you are used to PHP code, where empty($element) does also check for isset($element). In Java this is not the case.
You can memorize that easily, because the method is directly called on the list (the method belongs to the list). So if there is no list, then there is no method. And Java will complain that there is no list to call this method on.
You can use your own isEmpty (for multiple collection) method too. Add this to your Util class.
public static boolean isEmpty(Collection... collections) {
for (Collection collection : collections) {
if (null == collection || collection.isEmpty())
return true;
}
return false;
}

What should int compareTo() return when the parameter string is null?

It is said that when input parameter is null, compareTo() should throw a NullPointerException. However, I am implementing a class which needs to compare fields with the type of String. These fields need not to be mandatory. I wonder in this case,
1) What should I return when the input is null? Should any not-null strings lexicographically bigger or smaller than null?
and
2) If this is considered bad practice, is there any supporting arguments? Should I force the user to use empty strings instead? If using empty string, won't that confuse the case in which the field is not applicable and the case in which the field is empty? And if exception must be thrown, then except from warning the user in the manual, what else could/shall I do?
EDIT: I might not express myself clearly here, but in the program I am implementing, the strings that could be null are all fields or a class, which should not be null. In other words, the objects comparedTo() uses could not be null, just their private fields could be. So in this case, I believe if I implement compareTo() properly, it would not violate the transitive requirement since classes with null fields would be considered the same always. Am I right or am I interpreting this wrong?
Thank you all for the answers!
From javadoc for Comparable
Note that null is not an instance of
any class, and e.compareTo(null)
should throw a NullPointerException
even though e.equals(null) returns
false.
Yes, there is no problem allowing null for instance fields - just make sure its sorting order is defined. Most natural would be putting it either before or after all real strings, but you could do anything here, just do it consistently. (For example, you could sort null like "null".)
Here is an example implementation for a single member:
class Example implements Comparable<Example> {
#Nullable
private String member;
// TODO: getter, setter, constructor, ...
public int compareTo(Example that) {
if(this.member == null)
if(that.member == null)
return 0; //equal
else
return -1; // null is before other strings
else // this.member != null
if(that.member == null)
return 1; // all other strings are after null
else
return this.member.compareTo(that.member);
}
}
Please note that the specification of Comparable.compareTo() only has a constraint for o.compareTo(null) (which should behave just like - null.compareTo(o), i.e. throw a NullPointerException), but not about how null fields are handled (it doesn't mention fields at all, so a class could return whatever it wants, as long as the antisymmetry, reflexivity and transitivity is ensured).
It would be a bad practice to not throw an exception because it violates the transitive antisymmetric nature of compareTo.
From Comparable.compareTo documentation:
The implementor must ensure
sgn(x.compareTo(y)) ==
-sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must
throw an exception iff y.compareTo(x)
throws an exception.)
The implementor must also ensure that
the relation is transitive:
(x.compareTo(y)>0 && y.compareTo(z)>0)
implies x.compareTo(z)>0.
Finally, the implementor must ensure
that x.compareTo(y)==0 implies that
sgn(x.compareTo(z)) ==
sgn(y.compareTo(z)), for all z.
More importantly, it's a bad idea to use compareTo on your objects to compare them with strings, for the same reason: sign(obj.compareTo(str)) != -sign(str.compareTo(obj)). Implement a custom Comparator and do whatever you want in it.
You need to decide if null is greater-than or less-than to a non-null value. You can design compareTo to meets the needs of your class's natural ordering, thus it is not bad practice.
Because the documentation of compareTo states that it should throw a NullPointerException, you should follow those guidelines so your implementation is consistent with the interface documentation. This also handles the questions of whether or not non-null strings are lexicographically smaller or bigger than null.
You have a couple of options on how to handle this. If empty and not-applicable are different, then you should probably wrap the string field in your own field class. For example, say you could create a type of MyField that might have an isApplicable method, which indicates if the field is applicable to this case (or something similar). Or you could rethink your design and be sure that an empty string and N/A really are two different things. If they are, you do need a way to differentiate between the two.
In addition to Paulo Ebermann's accepted answer, if you need to handle ASC/DESC order, you would do this. (We're assuming that NULLs always come before Non-NULLs in normal ascending order, otherwise for descending.)
final boolean sortAsc = false; // Suppose this TRUE/FALSE is for ASC/DESC
objects.sort(new Comparator<Example>() {
#Override
public int compare(Example e1, Example e2) {
if (e1.getMember() == null && e2.getMember() == null) {
return 0; // Both NULLs are equal
}
else if (e1.getMember() == null && e2.getMember() != null) {
return sortAsc ? -1 : 1; // NULLs should precede non-NULLs in ascending order, follow in descending order
}
else if (e1.getMember() != null && e2.getMember() == null) {
return sortAsc ? 1 : -1; // Non-NULLs should follow NULLs in ascending order, precede in descending order
} else {
// Both non-NULLs
return sortAsc ? e1.getMember().compareTo(e2.getMember())
: e2.getMember().compareTo(e1.getMember());
}
}
});

Categories

Resources