what must be hashcode of null objects in Java? - 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;
}

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!");
}

Number of calls of hashCode() and equals() in case of HashSet.contains() if hashcode returns a constant value

I have read through Java docs pages, but I am not able to explain, why number of calls of hashCode() and equals() is varying like this?
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class NumberOfCalls {
int field;
public int getField() {
return field;
}
public NumberOfCalls(int field) {
this.field = field;
}
#Override
public int hashCode() {
System.out.println("In Hashcode method.");
return 10;
}
#Override
public boolean equals(Object obj) {
System.out.println("In Equals Method");
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
NumberOfCalls other = (NumberOfCalls) obj;
if (field != other.field)
return false;
return true;
}
public static void main(String[] args) {
NumberOfCalls object1 = new NumberOfCalls(5);
NumberOfCalls object2 = new NumberOfCalls(6);
NumberOfCalls object3 = new NumberOfCalls(5);
Set<NumberOfCalls> set = new HashSet<NumberOfCalls>();
set.add(object1);
set.add(object2);
Iterator<NumberOfCalls> it = set.iterator();
System.out.print("Size of set is : " + set.size()
+ "\nObject fields values present in set are : ");
while (it.hasNext()) {
System.out.print(it.next().getField() + " ");
}
System.out.println("\n---------------------------------------------------");
System.out.println("Now checking number of calls -- ");
System.out.println("Object1 is present in set ? - " + set.contains(object1)+"\n");
System.out.println("Object2 is present in set ? - " + set.contains(object2)+"\n");
System.out.println("Object3 is present in set ? - " + set.contains(object3)+"\n");
}
}
Output for above code is
In Hashcode method.
In Hashcode method.
In Equals Method
Size of set is : 2
Object fields values present in set are : 6 5
---------------------------------------------------
Now checking number of calls --
In Hashcode method.
In Equals Method
Object1 is present in set ? - true
In Hashcode method.
Object2 is present in set ? - true
In Hashcode method.
In Equals Method
In Equals Method
Object3 is present in set ? - true
Questions:
Why hashCode() and equals() called one-one time in case of object1 but not object2 (only hashCode() is called in this case)?
Why equals() is called twice in case of object3?
When you add an element to a Set it gets stored in a Map internally where key is the object you pass in and value is set to null. Internally Map maintains an array (buckets) of linked list. These arrays can also be referred as buckets. The index of the bucket is evaluated using hashCode() method.
In your case since hashCode() returns a constant value, all values put into Set will go in the same bucket. So for the first call set.add(object1) internal structure will be something like
bucket [object1 -> null]
Since each bucket contains a linked list, elements stored in the list has a pointer to the next element. Since only one element is added to the list, pointer points to null.
For next call set.add(object2) data structure will look like
bucket [object2 -> object1 -> null]
Now whenever you call set.contains(some_object), hashCode() will be called to find out correct bucket. This call also returns reference to the first element.
Answer to first question:
So when you call set.contains(object2) it actually returns reference to object2. Now if you look at the HashMap class' code it first compares if this reference is same as the reference passed in, using == operator. Since in this case it is same so it does not call equals() method. Below is the code snippet from HashMap class:
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e;
This should explain your first question.
Answer to second question:
When you call set.contains(object3), bucket index is calculated and reference to object2 is returned. Now object2 == object3 returns false so Map calls object3.equals(object2) method (first call to equals() method) to check if both objects are meaningfully equivalent. This also returns false, so it traverses list and returns reference to the next element in the list, which is object1.
Again object1 == object3 returns false so Map calls object3.equals(object1) (second call to equals() method) method to check if both objects are meaningfully equivalent.
This results in 2 calls to equals() method.

Compare the return value of a method when expected return type and return value are passed as string parameters

To give a little background on what I am trying to do, please refer my previous question :
Run a java method by passing class name and method name as parameter
So basically I am trying to call a method and test its return value. I'll read the following parameters from an xml or database : The method class,name,parameters and return value.
Then I'll execute the method and compare the output.
The code looks like this as of now :
public static void main(String[] args) throws IOException {
runTheMethod("CarBean","getColor","java.lang.String","Red");
}
public static void runTheMethod(String className, String methodName, String expectedReturnType, Object expectedReturnValue){
try {
Object classObj = Class.forName(className).newInstance();
Method method = classObj.getClass().getMethod(methodName);
Object returnVal = method.invoke(classObj);
if(expectedReturnValue.getClass().getName().equals(expectedReturnType)){
// This is the problem portion
System.out.println("Test passed : " + expectedReturnValue.equals(returnVal));
}else{
System.out.println("Expected return object type does not match actual return object type");
}
} catch (InstantiationException | IllegalAccessException
| ClassNotFoundException | NoSuchMethodException | SecurityException | IllegalArgumentException | InvocationTargetException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Carbean is a user defined pojo :
public class CarBean {
private String brand;
private String color = "Red";
public CarBean (){
}
public CarBean (String brand, String color){
this.brand= brand;
this.color= color;
}
/**
* #return the brand
*/
public String getBrand() {
return brand;
}
/**
* #param the brand to set
*/
public void setBrand(String brand) {
this.brand= brand;
}
/**
* #return the color
*/
public String getColor() {
return color;
}
/**
* #param the color to set
*/
public void setColor(String color) {
this.color= color;
}
#Override
public boolean equals(Object o){
if(o == null)
return false;
if(!(o instanceof CarBean))
return false;
CarBean other = (CarBean) o;
if(this.brand!=null && this.color!=null){
if(this.brand.equals(other.brand) && this.color.equals(other.color))
return true;
else
return false;
}else{
return false;
}
}
#Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + this.brand.hashCode();
hash = 31 * hash + this.color.hashCode();
return hash;
}
}
Now this works fine for the current code - return type is String and I can compare using equals.
But what if the method returns a BigDecimal or List? Is there a generic way I can compare multiple object types?
I am assuming that for a user defined java beans (pojo) I can override the equals() and hashcode() to compare it. Referring my blog for details:
http://javareferencegv.blogspot.com/2014/10/overriding-equals-and-hashcode-for-pojo.html
Any further suggestion is appreciated.
As far as creating objects from string values in your XML file. You basically already know how to do this. You just need to put the class name for the return type in the XML file. Then you can create your expected return value. For example:
Object newInstance(String cls, String arg) throws LotsOfExceptions {
return Class.forName(cls).getConstructor(String.class).newInstance(arg);
}
Object obj = newInstance("java.math.BigInteger", "1000");
So you can create a BigInteger from an XML file. If you want to create objects that do not define String constructors then you need to store some other information in the file that tells your program how to turn it in to an object. Maybe you should look in to abstract factory patterns. Another (more complicated) scheme would be to serialialize an object, then encode the bytes as base 64 so you can store it as text.
And before I go any further, I want to point out that running arbitrary Java commands from text input is unsafe. It would be safer if you were keeping a whitelist of allowed classes so that classes like System and File were off limits. It's OK to just experiment with this yourself, but in practice this is very unstable unless you are taking precautions.
On the subject of comparisons, you need to understand that equality is a concept that differs greatly from type to type. In general equals is a correct way to compare, because it is the equality that a class has defined for itself. If a class does not override equals, then it does not have a concept of value equality.
There are other ways to compare, for example, you could use reflection to compare two object's internal states.
Using reflection has issues though:
It is actually pretty complicated to write yourself.
Objects that define value equality through equals may have transient internal state that is deliberately not compared. So if we compare with reflection we are disregarding the value equality that a class may have defined. (And you may get unexpected results. For example, some versions of String calculate hashCode lazily.)
You might see this Q&A for a few libraries that do a reflection comparison already.
Here is a simple example of the kind of thing that is possible to do:
boolean publicallyEqual(Object a, Object b) throws IllegalAccessException {
if(a.getClass() != b.getClass())
return false;
for(Field f : a.getClass().getFields()) {
Object af = f.get(a);
Object bf = f.get(b);
if(af == null ? bf != null : !af.equals(bf))
return false;
}
return true;
}
That example compares public fields by equals, so it works for very simple objects (like a java.awt.Point). More complicated routines would compare the fields recursively and account for arrays.
Reflection could be an appropriate approach for something like unit testing of deserialization, where an object maybe doesn't define a value equality but we want to see if it got deserialized with a correct state.
The problem with your equals and hashCode is that:
Your equals considers an object not equal to any other object if their brand or color field is null.
if(this.brand!=null && this.color!=null){
...
}else{
return false;
}
It means that a CarBean(null, null) is not equal to a CarBean(null, null). Generally equals doesn't exhibit this type of behavior. For example, even a NaN equals another NaN by Double#equals comparison.
Your hashCode throws a NullPointerException if brand or color is null.
The corrected implementations would be as follows:
#Override
public boolean equals(Object o){
if(!(o instanceof CarBean)) // also this already evaluates
return false; // to false if o is null
CarBean other = (CarBean) o;
if(brand == null ? other.brand != null : !brand.equals(other.brand))
return false;
if(color == null ? other.color != null : !color.equals(other.color))
return false;
return true;
}
#Override
public int hashCode() {
int hash = 17;
hash = 31 * hash + (brand == null ? 0 : brand.hashCode());
hash = 31 * hash + (color == null ? 0 : color.hashCode());
return hash;
}
(And if null is an invalid state, then the constructors and setters should throw exceptions rather than letting the error trickle to your equals and hashCode.)
If your class implements Comparable, you can add a public int compareTo(Object o) function.
Then you can call it using int result = yourObject.compareTo(anotherObject);
But keep in mind that the function return an int. < 0 if yourObject is smaller 0 if it's equal and > 0 if it's greater.
You can compare your object to different objects using instanceOf inside compareTo(Object o) but you need to specify how the comparison should be handled with a specific object, Java will not guess for you
So I see two points here.
When two Java objects are considered equal?
Let o1 and o2 be objects. They are equal if and only if o1.equals(o2) and o2.equals(o1);
So you can just use equals method ( with respect to null references). (Lists and BigDecimals both have overriden equals method)
That if some POJO doesn't override equals?
Well you can think that two objects are equal if they belongs to same class and values returned from all getters are equals. Thats a dangerous road to take. But if you really want to do it java.beans package can help you.
All java classes are descendant of the Object class. The Javadoc of Object class defines the general contract for methods equal and hashcode. Extracts :
The equals method implements an equivalence relation on non-null object references
It is reflexive: for any non-null reference value x, x.equals(x) should return true.
It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
For any non-null reference value x, x.equals(null) should return false.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
These are general java requirements, so you can safely assume that all classes you test respect them. The good part if that Java containers or arrays(*) implement equality in a sense that is coherent with the equality of their elements.
EDIT :
(*) For arrays equality, you will have to use Arrays.equals() - thanks to Nikolay Ivanov for noting it

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;
}

Best Practice in handling comparator

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.

Categories

Resources