Equals() and hashCode() method in Java

Object Equality

When it comes to Java ,there are two types of Object equality ,reference equality and object equality.

Reference Equality

Two references that refer to the same object on the heap are considered equal.If you want to check if two references are referring to the same object using the ‘==’ operator. The ‘==’ operator compare the bits in the variable.If both refers to the same object the bits will be equal.

Example:- We have a student class and create an object and two references which refer to the same object.

The two references sRef1 and sRef2 refer to s1 so the comparison operator return true.This is Reference equality.

Object Equality

Object equality is used to check if two references referring to two different objects are meaningfully equivalent.If you want to treat two different objects as equal you must override hashCode() and equals() method.Both the method have a default implementation in the class Object.The default behaviour of hashcode method is that each object will get a unique number (most versions of Java assign a hashcode based on the object’s memory address on the heap so now two objects will have the same hash code).The default implementation of equals method returns true if two references refer to the same object .It uses ‘==’ operator to check for equality.

Example:- In the Student class we have overridden hashCode() and equals() method and created our custom implementation for object equality.

Two student objects will be considered equal when they have the same first name, last name and student id and the hash code of the two objects are the same.

You need to override the equals method to create your implementation of of  object equality.

In the given example all the student objects s1,s2 and s3 are different as they have different firstname, lastname, department and different hashcode.

Now,I add a new constructor to send studentId as parameter to show object equality.

The two student objects s1 and s2 are created , which are meaning fully equivalent because as per the hashcode and equals method two objects are equal if they have same first name, last name and student Id and they have the same hashcode

Rules for hashCode() and equals() Method

  • If two objects are equal ,they must have matching hash codes.
  • If two objects are equal, calling equals on both the objects should return true.That is if a.equals(b) is true then b.equals(a) is also true
  • If two objects have the same hashcode they are not required to be equal.But if they are equal, they must have the same hashcode value.That is  a.equals(b) is true then a.hashCode() must be equals to b.hashCode() but not vice versa.
  • If you override equals()  ,you must override hashcode() method and vice versa
  • The default implementation of hashCode method is to generate a unique integer for each object on the heap. So, if you don’t override hashCode() method ,no two objects can ever be equal.
  • The default behaviour of equals method checks if the two references refers to the same object on the heap.If you don’t override this method no two objects will ever be considered equal since references to two different objects will always have a different bit pattern

I hope you liked this article.Happy Coding everyone 🙂

How HashMap works in Java1.8?

HashMap is a hash table implementation of Map interface in Java. A map contains a collection of key-value pairs where key maps to the value.
HashMap permits null values and null keys and it doesn’t permit duplicate keys.It is unordered so it doesn’t guarantee that the order will remain constant with time.
Hashmap provides constant time performance for operations like get or put,  provided the elements are distributed evenly among the buckets.

The performance of HashMap depends on two factors ,the initial capacity and load factor. The initial capacity is the number of buckets in the HashMap and the initial capacity is the initial size of the HashMap.The load factor is a measure of how full the hash map is allowed to get before it is resized (capacity is increased).When the number of entries in the hash table exceeds the product of the load factor and the current capacity, the hash table is rehashed (that is, internal data structures are rebuilt) so that the hash table has approximately twice the number of buckets.

The default load factor is .75 because this can be changed while creating the HashMap.

Basic structure of HashMap

Initially in HashMap when multiple keys land in the same bucket then values along with their keys are placed in a linked list. Since Java 1.8 HashMap is converted to binary tree when the number of elements in a bucket reached a certain threshold.

How hashCode() and equals () method impacts HashMap?

The hashCode() method converts an object into an integer form(this is basically the hash code of the object) ,this process is called hashing.The performance of the hashmap depends on the hashCode() method implementation.In HashMap the hashCode() is used to calculate the bucket where the key-value pair should land .

The equals() method is used to check if two objects are equal or not. HashMap use this method to determine if the key of the key-value pair being inserted already exists or not.

A bucket is one element of HashMap array.It is used to store node,each node contains a key-value pair.A bucket can have multiple key-value pairs which are implemented as linked list.If the number of nodes in the bucket reached a certain threshold the linked list is converted to binary tree.
The hashCode() and equals() method determines where the key-value pair lands (in which bucket)

The put method in HashMap

The put method is used to insert key value pairs in a HashMap. Here’s the steps:-

  • The hashCode() method is called to calculate the hashCode of the key . The hashCode determines the index that is the bucket where the key-value pair will be inserted.
  • The hashCode() and equals() method is called to check if the key being inserted, already exists in the bucket .So, each of the keys in the linked list or the binary tree is checked to match the key being inserted.If the key already exists in the bucket then replace the value of the key with the new value else create a new node and insert the  key-value pair in the Bucket.

The get method in HashMap

In get method the key is provided as the parameter and the value of the key is returned .

Here’s the steps:-

  • The hashCode() method is called to calculate the hashCode of the key.
  • Calculate the index which determines the index or the bucket which contains the key-value pair.Index is calculated based on the hashcode of the key.
  • Search for the key in the bucket.Compare each key in the bucket with the key passed in the get method using the equals and hashCode method.If the key matches with any of the keys in the bucket return the value associated with the key else return null.

Performance of HashMap

Until Java 1.7 ,the worst cast scenario ,when multiple hash code values end up in the same bucket values are placed in a linked list which reduces hash map performance from O(1) to O(n)

Since Java 1.8 when the number of items reaches a certain threshold in the linked list,it is converted to binary tree and when the number of elements are less than a certain threshold(due to deletion) they are converted back to linked list.This improves the worst case performance from O(n) to O(log n) .

I hope you enjoyed reading this article .Happy Coding 🙂

How to resolve package com.sun.image.codec.jpeg does not exist?

Sometimes the java project (usually a lower version of Java (1.6 or lower)) results in the following compilation error:-

INFO] Compiling 106 source files to /Users/JavaProject/src/java/web/target/classes [INFO] ————————————————————- [ERROR] COMPILATION ERROR : [INFO] ————————————————————- [ERROR] /Users/JavaProject//src/java/web/main/java/net/esi/ppc/presentation/service/CaptchaImageGenerator.java:[24,31] error: package com.sun.image.codec.jpeg does not exist [ERROR] /Users/JavaProject//src/java/web/main/java/net/esi/ppc/presentation/service/CaptchaImageGenerator.java:[25,31] error: package com.sun.image.codec.jpeg does not exist

To resolve this issue you can add the following in the pom.xml

<compilerArgument>

            -XDignore.symbol.file

</compilerArgument>

It’s basically an argument for the Java compiler. Also, adding the arguments “-XDignore.symbol.file” will depend on the build tool.

A much better solution is to rewrite the code without using the proprietary classes.Because you are not supposed to directly use the classes under the package com.sun.image.codec.jpeg

But if you have a legacy code which you can’t change, then this is the solution.

You can read the following post for more information :-https://www.oracle.com/technetwork/java/faq-sun-packages-142232.html

The package com.sun.image.codec.jpeg has been removed in Java 7 as mentioned in the Java SE 7 and JDK 7 Compatibility Guide.

Synopsis: The Non-standard com.sun.image.codec.jpeg Package is Retired

Description: The com.sun.image.codec.jpeg package was added in JDK 1.2 (Dec 1998) as a non-standard way of controlling the loading and saving of JPEG format image files. This package was never part of the platform specification and it has been removed from the Java SE 7 release. The Java Image I/O API was added to the JDK 1.4 release as a standard API and eliminated the need for the com.sun.image.codec.jpeg package.

Let me know if this solution worked for you .Happy Coding guys an gals 🙂

Loops in Java

Loops in java are used to execute a set of statements repeatedly until a condition is satisfied or to iterate a collection of objects.

There are 4 types of loop:-

  • The basic for loop
  • The enhanced for loop
  • The while loop
  • The do while loop
  • The forEach loop

The basic for loop

The basic for loop has the following syntax:-

for(initialization ; condition ;counter increment/decrement){

}

If we have only one statement in the for loop then the curly braces are not mandatory.

Step 1 :- The initialization part of the loop executes for the first time.

Step 2 :- The condition is checked .If the expression evaluates to true the statements inside the for block is executed else the control flow exits the loop that is step 4

Step 3 :- The counter is incremented or decremented.

We repeat 2 and 3 phases until the condition is not met and the for loop is terminated

Step 4 :- Exit the loop

The enhanced for loop

The enhanced for loop is used to iterate a collection of objects or an array in java

Syntax:-

for(data_type item:collection/array){

//statements ….

}

  • Item is the single item from the collection 
  • Collection /array is the variable which you have to iterate or loop through 

Here’s the flow of the enhanced for loop:-

  • Iterate through each item in the array /collection
  • Places each item in the variable 
  • Executes the body of the loop

The loop iterates through all the objects in the collection/array one by one.

The while loop

The while loop is used to execute a set of statements until a condition is satisfied.

Here’s the flow:-

  1. Loop starts with the condition.If the condition is true step 2 is executed.If false the loop exists that is step 3.
  2. The statements inside the loop is executed .Usually the statements also update the variable being used in the conditional statement(at the start of the loop)
  3. Exit the loop

The do while Loop

The do while loop make sure the statements in the block is executed at least once irrespective of the conditional expression in while .

Syntax :-

Do {

..//statements 

}while(expression);
It ends with a colon.

Here’s the flow:-

Step1 :- The statements is executed in the do while block 

Step2 :- The expression is evaluated.If it is true the statement in the block is executed else the control flow exists the do while block that is step3 

Step3 :- Exit the do while block.

The forEach method

In Java 1.8 a new forEach method is introduced to iterate the elements.It is defined in Iterable and Stream interface.It’s a default method in iterable interface.

We can loop a collection of objects using the forEach method as the collection interface extends the Iterable interface.

The forEach method take functional interface (Consumer ) as the arguments so we can use lambda expressions along with the forEach method.

That’s all about loops in Java.I hope you enjoyed reading this article.

Happy Coding 🙂



Default Methods In Java

Default methods allows us to add new functionality to new or existing interfaces without breaking the existing functionality of legacy code.

Prior to Java 1.8 interfaces did not allow default interfaces and it was very difficult to modify an existing interface without impacting the class which implemented the interface.For instance if a new method is added to an interface ,it  needs to be implemented in all the classes implementing that interface.

Example

Consider the following interface which is an existing piece of code:-

The interface is implemented by various branches of the Good Food Restaurant.

We later plan to add the restaurant working hours .But if we add it to the interface ,the method needs to be implemented in all the three classes.This can be a lot of work especially in big projects where the interface is implemented in several different classes and multiple new method are added in the interface.

Default method comes to the rescue in all these cases.With default methods its not mandatory for an implementing class to implement the default method , its optional.

A default method is defined in an interface and if the implementing class do provide the implementation of the default method then it overrides the default method definition.Here’s the summary when you implement an interface that contains a default method:-

  • Do not redefine the default method in the implementing class ,which lets you use the default method definitions whenever it is called.
  • Redefine the default method, in this case it is overridden

Extending an interface with a default method

The following rules apply when you extend an interface that contains a default method along with one more scenario:-

  • Do not redefine the default method in the implementing class ,which lets you use the default method definitions whenever it is called.
  • Redefine the default method, in this case it is overridden
  • Redeclare the default method which makes it abstract.

That’s all about default methods in Java.I hope you enjoyed reading this articles.