Sunday, 18 March 2018

Overriden Of Hashcode() and Equal() methods in Java

We will see benefit by overriding the hashcode() and equals() methods in java.

JVM will assign unique hashcode value for each and every object created and if we did not over ride the hashcode()) method, no way to get same hashcode value for two objects.

As equals() method compare two objects if they have same value or not, then what is the need of overriding hashcode() method?

To answer this ,we need to know about how hashcode will work in java.

As mentioned in above diagram each java object will be placed in bucket depending on hashcode value. Here it is not necessary every different object does have different hashcode value.  Two different objects might have same hashcode.

When we try to insert key in hashmap, it will check and get the hashcode value  and find the bucket and insert the object into it if any other object is not available in the same bucket. If some other object is already available in that bucket, then it will check for equals() method on key and override if key is same other wise i.e key is different, it will insert the other object in next node of same bucket.

If object does not override hashcode() method,  and if we use the object as key to store, then we will not get the object back as shown below.

package com.sample.java.testing;

public class OverrideHascodeBean {

    private String name;
    private int id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

}


package com.sample.java.testing;

import java.util.HashMap;

public class OverrideHascodeEquals {

    public static void main(String a[]){
        HashMap<OverrideHascodeBean, String> hashMap = new HashMap<OverrideHascodeBean, String>();
       
        OverrideHascodeBean bean1 = new OverrideHascodeBean();
        bean1.setId(001);
        bean1.setName("Java");       
       
        OverrideHascodeBean bean2 = new OverrideHascodeBean();
        bean2.setId(002);
        bean2.setName("J2ee");       
       
        OverrideHascodeBean bean3 = new OverrideHascodeBean();
        bean3.setId(003);
        bean3.setName("Spring");       
       
        OverrideHascodeBean bean4 = new OverrideHascodeBean();
        bean4.setId(001);
        bean4.setName("Java");
       
        hashMap.put(bean1, "First");
        hashMap.put(bean2, "Second");
        hashMap.put(bean3, "Third");
        hashMap.put(bean4, "FirstDup");
       
        for (OverrideHascodeBean bean : hashMap.keySet()) {
            System.out.println(hashMap.get(bean).toString());
           
        }
       
        //creating object similar to first.
        OverrideHascodeBean bean5 = new OverrideHascodeBean();
        bean5.setId(001);
        bean5.setName("Java");
       
        if (hashMap.get(bean5) == null) {
            // here we created object(5) which is similar to object(1) but when
            // we try to get the bean from map it is not able to find. As we did
            // not override Hashcode() and equals() method, duplicate objects
            // are added not replaced even if we pass same key.
            System.out.println("Objectn not found");
           
        }
    }
}

Output : Third
First
FirstDup
Second
Objectn not found

See below example when we override equals and hashcode methods and we will find the object if we pass duplicate object.

package com.sample.java.testing;

public class OverrideHascodeBean {

    private String name;
    private int id;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    @Override
    public boolean equals(Object o) {
        OverrideHascodeBean bean = (OverrideHascodeBean) o;
        return bean.id == this.id && bean.name.equals(this.name);

    }

    @Override
    public int hashCode() {
        return name.hashCode() + id;
    }

}


package com.sample.java.testing;

import java.util.HashMap;

public class OverrideHascodeEquals {

    public static void main(String a[]){
        HashMap<OverrideHascodeBean, String> hashMap = new HashMap<OverrideHascodeBean, String>();
       
        OverrideHascodeBean bean1 = new OverrideHascodeBean();
        bean1.setId(001);
        bean1.setName("Java");       
       
        OverrideHascodeBean bean2 = new OverrideHascodeBean();
        bean2.setId(002);
        bean2.setName("J2ee");       
       
        OverrideHascodeBean bean3 = new OverrideHascodeBean();
        bean3.setId(003);
        bean3.setName("Spring");       
       
        OverrideHascodeBean bean4 = new OverrideHascodeBean();
        bean4.setId(001);
        bean4.setName("Java");
       
        hashMap.put(bean1, "First");
        hashMap.put(bean2, "Second");
        hashMap.put(bean3, "Third");
        hashMap.put(bean4, "FirstDup");
       
        for (OverrideHascodeBean bean : hashMap.keySet()) {
            System.out.println(hashMap.get(bean).toString());
           
        }
       
        //creating object similar to first.
        OverrideHascodeBean bean5 = new OverrideHascodeBean();
        bean5.setId(001);
        bean5.setName("Java");
       
        if (hashMap.get(bean5) == null) {
            // here we created object(5) which is similar to object(1) but when
            // we try to get the bean from map it is not able to find. As we did
            // not override Hashcode() and equals() method, duplicate objects
            // are added not replaced even if we pass same key.
            System.out.println("Objectn not found");
           
        }else{
            //as we override hashcode and equals method, hashmap will replace the old value with new value if we pass give duplicate key
            System.out.println("Object found");
        }
    }
}


output: Second
Third
FirstDup
Object found
 

Saturday, 17 March 2018

Constructor Injection in Spring

Constructor injection is one of the approach to inject the dependency in spring  and we can inject the dependencies for primitive and string types using constructor method as shown below.

It requires spring core jar files to execute the below application.

1. Student bean which has some field to store student details. It is Bean in our example.
2. Application Context xml file to configure the student bean as spring bean.
3. Main class to execute the application.

Bean:

package com.bk.spring.test;

public class StudentBean {

    private int id;
    private String name;
    private String emailId;
    private String course;
    private double fee;

    StudentBean() {
        System.out.println("default constructor");
    }

    StudentBean(String name) {
        this.name = name;
    }
  
    StudentBean(int id) {
        this.id = id;
    }

    StudentBean(int id, String name, String emailId, String course, double fee) {
        this.id = id;
        this.name = name;
        this.emailId = emailId;
        this.course = course;
        this.fee = fee;
    }

    public void getStudentDetails() {
        System.out.println("Id is " + this.id + " name is " + name
                + " email id is " + emailId + " course is " + course
                + " fee is " + fee);
    }

}


Xml file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean name="student" class="com.bk.spring.test.StudentBean">
        <constructor-arg value="001"/>
        <constructor-arg value="Krishna" />
        <constructor-arg value="krishna@abc.com" />
        <constructor-arg value="Spring" />
        <constructor-arg value="2018" />
    </bean>
</beans>

Execution Program:

package com.bk.spring.test;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;

public class SpringConDITest {

    public static void main(String a[]) {

        Resource res = new ClassPathResource("applicationContext.xml");
        BeanFactory factory = new XmlBeanFactory(res);
        StudentBean bean = (StudentBean) factory.getBean("student");
        bean.getStudentDetails();

    }

}

Output : Id is 1 name is Krishna email id is krishna@abc.com course is Spring fee is 2018.0

If we comment all constructor args tags in xml file, then default constructor will call

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean name="student" class="com.bk.spring.test.StudentBean">
        <!-- <constructor-arg value="001"/>
        <constructor-arg value="Krishna" />
        <constructor-arg value="krishna@abc.com" />
        <constructor-arg value="Spring" />
        <constructor-arg value="2018" /> -->
    </bean>
</beans>
Output : default constructor
Id is 0 name is null email id is null course is null fee is 0.0

Similar way we cam initialize string parameterized constructor as shown below

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean name="student" class="com.bk.spring.test.StudentBean">
        <!-- <constructor-arg value="001"/> -->
        <constructor-arg value="Krishna" />
        <!-- <constructor-arg value="krishna@abc.com" />
        <constructor-arg value="Spring" />
        <constructor-arg value="2018" /> -->
    </bean>
</beans>

Output : Id is 0 name is Krishna email id is null course is null fee is 0.0

We need to take care of order of elements to pass like if i change the xml file as below, then second value will print email id. Just what ever we give test, it will assign to variable. No error but order also need to follow for our safety.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean name="student" class="com.bk.spring.test.StudentBean">
        <constructor-arg value="001"/>
        <constructor-arg value="krishna@abc.com" />
        <constructor-arg value="Krishna" />
        <constructor-arg value="Spring" />
        <constructor-arg value="2018" />
    </bean>
</beans>

Output: Id is 1 name is krishna@abc.com email id is Krishna course is Spring fee is 2018.0

Suppose if we have multiple single parameterized constructor and if we want to initialize specific constructor we need to specify the type and if we did not specify the type by default it will initialize the string parameterized constructor.

Below will call string param constructor;

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean name="student" class="com.bk.spring.test.StudentBean">
        <constructor-arg value="001"/>
        <!-- <constructor-arg value="Krishna" />
        <constructor-arg value="krishna@abc.com" />
        <constructor-arg value="Spring" />
        <constructor-arg value="2018" /> -->
    </bean>
</beans>

Output: Id is 0 name is 001 email id is null course is null fee is 0.0

Below will call int param constructor

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    <bean name="student" class="com.bk.spring.test.StudentBean">
        <constructor-arg value="001" type="int"/>
        <!-- <constructor-arg value="Krishna" />
        <constructor-arg value="krishna@abc.com" />
        <constructor-arg value="Spring" />
        <constructor-arg value="2018" /> -->
    </bean>
</beans>

Output : Id is 1 name is null email id is null course is null fee is 0.0

Friday, 16 March 2018

Print different patterns using Java

We can print different pattern shapes using for loop in java programming.

package com.sample.java.testing;

public class PrintPatternTest {

    public static void main(String[] args) {
    //================================   
        for (int j = 0; j < 9; j++) {
            for(int k =0; k <= j; k++){
                System.out.print("*");
            }
            System.out.println("");
           
        }



*
**
***
****
*****
******
*******
********
*********
**********
     //===============================  
        for (int j = 9; j >= 0; j--) {
            for(int k =0; k <= j; k++){
                System.out.print("*");
            }
            System.out.println("");
           
        }

*********
********
*******
******
*****
****
***
**
*
//---------------------------------------------------       
        for (int j = 1; j < 9; j++) {
            for(int k =1; k <= j; k++){
                System.out.print(k);
            }
            System.out.println("");
           
        }
1
12
123
1234
12345
123456
1234567
12345678
//------------------------------------       
        for (int j = 9; j > 0; j--) {
            for(int k =2; k <= j; k++){
                System.out.print(k-1);
            }
            System.out.println("");
           
        }
12345678
1234567
123456
12345
1234
123
12
1
//============================       
        int startNumber = 1;
       
        for (int j = 0; j < 9; j++) {
            for(int k =0; k <= j; k++){
                System.out.print(startNumber + " ");
                startNumber = startNumber + 1;
            }
            System.out.println("");
           
        }
  1
2 3
4 5 6
7 8 9 10
11 12 13 14 15
16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31 32 33 34 35 36
37 38 39 40 41 42 43 44 45
//======================     
        int space = 9;
        for (int j = 0; j < 9; j++) {
            for(int k =0; k <= space; k++){
                System.out.print(" ");
            }
            space = space - 1;
            for (int i = 0; i < j+1; i++) {
                System.out.print("*");
            }
            System.out.println("");
        }
          *
         **
        ***
       ****
      *****
     ******
    *******
   ********
  *********
//------------------------------------------     
        int space1 = 9;
        for (int j = 0; j < 9; j++) {
            for(int k =0; k <= space1; k++){
                System.out.print(" ");
            }
            space1 = space1 - 1;
            for (int i = 0; i < j+1; i++) {
                System.out.print("* ");
            }
            System.out.println("");
        }
       
    }

}
           *
         * *
        * * *
       * * * *
      * * * * *
     * * * * * *
    * * * * * * *
   * * * * * * * *
  * * * * * * * * *

Some Interesting things in Java

As s java developer we need to know some of the basic but important things while coding. I found some of the below in my experience.

1. Divided by zero: Generally if we divide any number by using / operator , we will get arithmatic exception. Similarly, when some one asked me what is the output of 1/0.0, without any hesitation i said, it will give run time exception. But answer is wrong. Actually it will print INFINITY.

package com.sample.java.testing;

public class DividedByDoubleTest{

    public static void main(String[] args) {
        int i = 10;
        System.out.println(i / 0.0);//Infinity
        System.out.println(i % 0.0);//nan
       
        System.out.println(i / 2);//quotient
        System.out.println(i % 2);//reminder
        System.out.println(i % 0);//java.lang.ArithmeticException: / by zero
        System.out.println(i / 0);
    }

}


Output:
 Infinity
NaN
5
0
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at com.sample.java.testing.PrintTriAngleTest.main(PrintTriAngleTest.java:12)

2. Overriding: To override any method in sub class, we need to have same signature, return type and method name and  sub class can not modify the method behavior like it can not throws any exception if super class doe not do any like that.

Coming to Static method overridden it seems like overridden but actually not .Because static method is bind with class name. Hence we can have same static method name both is super class and subclass like separate methods not like Overridden.We can access super class static method with super class and subclass static method with subclass but coming to instance method, we can access the super class methods with subclass. And also we can access the overridden methods of subclass by using the parent class reference if we assign subclass object to parent class reference .This is what run time polymorphism.

We need multiple classes to get overridden feature.

3. Overloading:  One class can have different methods with same name but either argument return type or argument count should be different.

4. Static/Instance : We can access the static variables in side instance methods and also we can access static fields/methods using instance of class.  Because we are creating object for the class only so variables declared in class can be accessible using object of class which are either static or instance fields.Static filed will store in method area and when JVM loads the class first it loads static blocks/fields. But we can not access instance variable//methods using the class name because instance fields are accessible / memory allocated when we create the object and these are stored in heap memory.

5. Declaration : This is what just we have just write variable declaration etc.

String s;//Declaration
int k = 10;

6. Initiation: When we create object with new Keyword, then memory will allocate and reference for an object is created. So that we can access all the methods or fields using reference.


7. Initialization : Default values will be allocated for the filed into Memory. This is what happen by Constructor when we called. All variables will be initialized with some value in memory here.

ClassTest t;//Declaration
 t = new ClassTest(); //initiation and initialization memory and initialize the variable t.



Thursday, 15 March 2018

Design Patterns In Java

Design patterns provides general solution for common design problems and initially design patterns were used in Object Oriented Programming. Later on realized that Design pattern need for other programming approaches to design software projects.

I general Programmers need some set of ideas/rules to design any use case or to develop any software application. In that case if we consider idea from already existing/developed application,  it will easy for us to implement that application and also it is time saving and effort saving process.

If we have some of problems in our application development and if we solve the problems by following some approach and if we share that approach we follows to solve an issue, it will be helpful for other to use the same approach instead of writing new solution. This approaches we can consider as design patterns.

So we can call a design pattern as a collection of rules which describes how to perform certain tasks during the software development.

Some of advantages of Design Patterns:
  • They are already proved and verified as they have been built up on the knowledge and experience of developers.
  • Design patterns are reusable ideas in multiple projects
  • Design patterns captures the Software engineering experiences.  

We have Java/J2EE design patterns.

Front controller design pattern: It is J2EE design pattern used to handle multiple request in web application.

If we need of control which needs to handle and co ordinate  all coming multiple user request like consider a online shopping website. Here we need to maintain some sequence of steps and if multiple users are logged in at time, then we need to handle consistency among multiple users. So some piece of code performing input processing and scattered across multiple objects and it is difficult to change the behavior of an object at run time.

We can go for front controller design patterns to provide the solution for above problem. Here we can use Front controller to handle multiple requests.




With this design pattern implementation, every request  goes to front controller before it processed. The controller may forward the request to associate helper to verify authentication details of the user.
If we take Spring framework, Dispatcher controller will work as Front controller for application. i.e any request comes to server will be processed by dispatcher servlet.

Protoype Design Pattern in Java

Design patterns are programming language independent solution providers for specific problems. Design patterns will have some specific rules to provide solutions and we need to follow some rules to implement design pattern. We have different kind of design patterns for different types of problems. Suppose if we want to create class and we want to create only object for that class,  we can go for Singleton design pattern.

Suppose if we want to just clone the object instead of creating new one ,we can choose Prototype Design Pattern. We can also customize the cloned object as per our requirement if we use prototype design pattern. This pattern will follow java cloning feature.

Advantages:

1. With this design pattern, we can reduce the sub class mechanism.
2. It can add objects at runtime.
3. It avoids complexity to create objects.

Based on above advantages, we can go for this design pattern, if we come across any of above mentioned advantages like if we need objects which are slimier to already existing objects or if we need object creation dynamically at run time and if we want to perform some DB CRUD operations instead of creating new object every time to get data, we can clone existing one and can modify the data.

Example:

package com.sample.java.testing;

import java.util.ArrayList;
import java.util.List;

public class CoursePrototype implements Cloneable {

    List<String> courses;
  
    public CoursePrototype(){
        courses = new ArrayList<>();
    }
  
    public CoursePrototype(List<String> courses){
        this.courses = courses;
    }
  
    public void addCourse(){
        courses.add("J2SE");
        courses.add("J2EE");
        courses.add("Spring");
        courses.add("Hibernate");
    }
  
    public Object clone(){
        //if we do this temp list here, just we can clone object with list
        //other wise we need to call addcoures()method on each of cloned object
        List<String> tempCcourses = new ArrayList<>();
        for (String string : this.getCourseList()) {
            tempCcourses.add(string);
        }
        return new CoursePrototype(tempCcourses);
    }
  
    public List<String> getCourseList(){
        return courses;
    }
  

}


package com.sample.java.testing;

import java.util.List;

public class ProtoTypeDemoTest {

    public static void main(String[] args) {

        CoursePrototype coursePrototype = new CoursePrototype();
        coursePrototype.addCourse();
        System.out.println(coursePrototype.getCourseList());
        CoursePrototype cloneCoursePrototype = (CoursePrototype) coursePrototype.clone();
        //cloneCoursePrototype.addCourse();//as we already add dummy list inside clone method
        System.out.println(cloneCoursePrototype.getCourseList());//same as new object becoz we did not do any chnages
        List<String> list = cloneCoursePrototype.getCourseList();
        list.add("Design Pattern");//can modify as per our requirement
        System.out.println(cloneCoursePrototype.getCourseList());//it is different than original object
        System.out.println(coursePrototype.getCourseList());//no changes in original object
      
        CoursePrototype cloneCoursePrototype1 = (CoursePrototype) coursePrototype.clone();
        //cloneCoursePrototype1.addCourse();//as we already add dummy list inside clone method
        List<String> list1= cloneCoursePrototype1.getCourseList();
        list1.remove("Hibernate");//can modify as per our requirement
        System.out.println(cloneCoursePrototype1.getCourseList());//it is different than original object
    }

}


Output:
[J2SE, J2EE, Spring, Hibernate]
[J2SE, J2EE, Spring, Hibernate]
[J2SE, J2EE, Spring, Hibernate, Design Pattern]
[J2SE, J2EE, Spring, Hibernate]

Wednesday, 14 March 2018

IOC Vs DI

IOC Inversion of control: If someone else is creating the objects for us rather than we are creating using new Object and we can call that some one as IOC container. i.e IOC container will take the part of creating Objects which we needed. As object is inverted we are calling it is Inversion of Control. It is not programmer, some one else who controlling the object.

If we consider Spring framework, Spring IOC will take of Bean creations.

Dependency Injection: We normally hardcode the dependency as shown below.

package com.sample.java.testing;

public class DependentObjectTest {

    DependencyObjectTest dependentObjectTest;
   
    DependentObjectTest(){
        dependentObjectTest = new DependencyObjectTest();//tight coupling
    }

}

DI is nothing but injecting the dependency rather than hardcoding it. WE can inject the dependency either  setter method and constructor.

Constructor Injection:

package com.sample.java.testing;

public class DependentObjectTest {

    DependencyObjectTest dependentObjectTest;
   
       DependentObjectTest(DependencyObjectTest dependentObjectTest){
        this.dependentObjectTest = dependentObjectTest;       
    }
}

Setter Injection:

package com.sample.java.testing;

public class DependentObjectTest {

    DependencyObjectTest dependentObjectTest;
   
     public DependencyObjectTest getDependentObjectTest() {
        return dependentObjectTest;
    }

    public void setDependentObjectTest(DependencyObjectTest dependentObjectTest) {
        this.dependentObjectTest = dependentObjectTest;
    }
     
}

Multi level dependecy: like class1 depends on class2 and classs2 is dependent on class3 etc.

package com.sample.java.testing;

public class DependencyObjectTest {
   
    public void printMessage(){
        System.out.println("DependencyObjectTest printMessage");
    }

}

package com.sample.java.testing;

public class Dependent1 {

    DependencyObjectTest dependencyObjectTest;
   
    Dependent1(DependencyObjectTest dependencyObjectTest){
        this.dependencyObjectTest =dependencyObjectTest;
    }
   
    public void printMessage(){
        System.out.println("Dependent1 printMessage");
        dependencyObjectTest.printMessage();
    }
}

package com.sample.java.testing;

public class Dependent2 {
   
    Dependent1 dependent1;
   
    Dependent2(Dependent1 dependent1){
        this.dependent1 = dependent1;
    }
   
    public void printMessage(){
        System.out.println("Dependent2 printMessage");
        dependent1.printMessage();
    }

}

package com.sample.java.testing;

public class Dependent3 {

    Dependent1 dependent1;
    Dependent2 dependent2;
   
    Dependent3(Dependent1 dependent1, Dependent2 dependent2){
        this.dependent1 = dependent1;
        this.dependent2 = dependent2;
    }
   
    public void printMessage(){
        System.out.println("Dependent3 printMessage");
        dependent1.printMessage();
        dependent2.printMessage();
    }
}

package com.sample.java.testing;

public class DependentDemoTest {

    public static void main(String[] args) {

        DependencyObjectTest dependencyObjectTest = new DependencyObjectTest();
        Dependent1 dependent1 = new Dependent1(dependencyObjectTest);
        Dependent2 dependent2 = new Dependent2(dependent1);
        Dependent3 dependent3 = new Dependent3(dependent1, dependent2);
        dependent3.printMessage();
    }

}

What is Spring Framework

Spring framework is one of mostly used framework for Enterprise application development.
Spring is multi-tier open source lightweight application framework. Spring framework provides support to simplify the development of  enterprise application in each and every layer. It also support to integrate various other frameworks with it if required. We can implement the complete enterprise application using with spring framework alone.

Dependency injection and Inversion Of Control(IOC):

Spring framework implements the IOC principle to made dependency injection very easy and flexible. We can remove the dependency or tight coupling in between java classes with IOC.

Consider below sample programms.

package com.sample.java.testing;

public class DependencyObjectTest {

}


package com.sample.java.testing;

public class DependentObjectTest {

    DependencyObjectTest dependentObjectTest;
  
    DependentObjectTest(){
        dependentObjectTest = new DependencyObjectTest();//tight coupling
    }
  
 }

Here we have  dependency in between DependecyTest  and DependentObjectTest  objects. these are tightly coupled. Ad if we made changes to resource, we need to do some code changes in our classes as well.

The same can be achieved with IOC as shown below by removing the dependency at compile time.

package com.sample.java.testing;

public class DependentObjectTest {

    DependencyObjectTest dependentObjectTest;

    DependentObjectTest(DependencyObjectTest dependentObjectTest){
        this.dependentObjectTest = dependentObjectTest;      
    }
}


Here both object are loosely coupled i.e if we no need to make any changes from client side, even if we made any changes to resource.

Dependency Injection(DI):

Dependency Injection is design pattern which implements IOC principle to remove the dependencies from programming. Hence we can manage application easily. Dependency Injection will make our code as loosely coupled which makes it decreases the coupling between class and it's dependency object.

Advantages of  Spring Framework: Below are some of advantages we get with Spring Framework

1. Lightweight
2. Inversion of Control which helps loose coupling in between classes.
3. Declarative support
4. Easy and fast Development

Tuesday, 13 March 2018

Factory Design Pattern in Java

We will use Factory design pattern when we have one super class and many sub classes and we need to return instance of subclass based on input.  Factory class will take the responsibility for object creation instead of client program

Super Class:
package com.sample.java.testing;

public abstract class FactoryPatternVehicleClass {
   
    public abstract int getWheels();
    public abstract String getEngineType();
   
    @Override
    public String toString(){
        return this.getEngineType() + " has " + this.getWheels() + " wheels";
    }

}

Subclass1:
package com.sample.java.testing;

public class FactoryPatternCarClass extends FactoryPatternVehicleClass {

    int noOfWheels;
    String engineType;

    public FactoryPatternCarClass(int noOfWheels, String engineType) {
        this.noOfWheels = noOfWheels;
        this.engineType = engineType;
    }

    @Override
    public int getWheels() {
        return this.noOfWheels;
    }

    @Override
    public String getEngineType() {

        return this.engineType;
    }

}

Subclass2:
 
package com.sample.java.testing;

public class FactoryPatternBusClass extends FactoryPatternVehicleClass {

    int noOfWheels;
    String engineType;

    public FactoryPatternBusClass(int noOfWheels, String engineType) {
        this.noOfWheels = noOfWheels;
        this.engineType = engineType;
    }

    @Override
    public int getWheels() {
        return this.noOfWheels;
    }

    @Override
    public String getEngineType() {

        return this.engineType;
    }

}

Factory class to return Objects:
 
package com.sample.java.testing;

public class FactoryPatternFactoryClass {

    public static FactoryPatternVehicleClass getVehicleObject(
            String objectType, int noOfWheels) {

        if (null != objectType && objectType.equalsIgnoreCase("Bus")) {
            return new FactoryPatternBusClass(noOfWheels, objectType);
        } else if (null != objectType && objectType.equalsIgnoreCase("Car")) {
            return new FactoryPatternBusClass(noOfWheels, objectType);
        }
        return null;

    }

}

Client class to test:
 
package com.sample.java.testing;

public class FactoryPatternDemoTest {

    public static void main(String a[]) {
        FactoryPatternVehicleClass factoryPatternBusClass = FactoryPatternFactoryClass
                .getVehicleObject("Bus", 6);
        System.out.println(factoryPatternBusClass);

        FactoryPatternVehicleClass factoryPatternCarClass = FactoryPatternFactoryClass
                .getVehicleObject("Car", 4);
        System.out.println(factoryPatternCarClass);
    }
}

Output:

Bus has 6wheels
Car has 4wheels
 

How HashMap works internally in Java

One of the most popular and important java interview question is how Hashmap will works and how it is different from Hashtable.

Hashmap will work on hashing principle. But it is not as easy as it seems. Hashing is mechanism to assigning unique hashcode to variable or attribute using algorithm for easy retrieve of elements. Hence best hashing algorithm should return same hashcode every time when it is applied on same object.
We will see below how hashing helps to store and retrieve elements from hashmap?.
Hashing uses hash functions to link key and value in Hashtable. We will store elements using put(key, value) and retrieve using get(key) methods from Hashmap.

When we call put method on Hashmap, hashcode() method of key is called and map will find the bucket location buy using hash function and stores value object in bucket. Here bucket is nothing but index of an internal array and it is known as table. Hashmap internally stores mapping in the form of Map.Entry object which contains both key and value objects.

Put method implementaion:

/**
     * Associates the specified value with the specified key in this map.
     * If the map previously contained a mapping for the key, the old
     * value is replaced.
     *
     * @param key key with which the specified value is to be associated
     * @param value value to be associated with the specified key
     * @return the previous value associated with <tt>key</tt>, or
     *         <tt>null</tt> if there was no mapping for <tt>key</tt>.
     *         (A <tt>null</tt> return can also indicate that the map
     *         previously associated <tt>null</tt> with <tt>key</tt>.)
     */
    public V put(K key, V value) {
        if (key == null)
            return putForNullKey(value);
        int hash = hash(key.hashCode());
        int i = indexFor(hash, table.length);
        for (Entry<K,V> e = table[i]; e != null; e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
                V oldValue = e.value;
                e.value = value;
                e.recordAccess(this);
                return oldValue;
            }
        }

        modCount++;
        addEntry(hash, key, value, i);
        return null;
    }

And when we try to retrieve elements by using get() method, we need to pass key value and here key object will generate same hashcode(generated when storing and it is mandatory to generate same hashcode to retrieve object. This is the reason Hashmap keys are immutable Ex: Strings) so that we can get the bucket location. If  we have only one Map.entry object, we can get it and this is object we stored earlier. But if we have any collision here, it will require more understanding to retrieve elements from same bucket location.

Get Method implementation:

/**
     * Returns the value to which the specified key is mapped,
     * or {@code null} if this map contains no mapping for the key.
     *
     * <p>More formally, if this map contains a mapping from a key
     * {@code k} to a value {@code v} such that {@code (key==null ? k==null :
     * key.equals(k))}, then this method returns {@code v}; otherwise
     * it returns {@code null}.  (There can be at most one such mapping.)
     *
     * <p>A return value of {@code null} does not <i>necessarily</i>
     * indicate that the map contains no mapping for the key; it's also
     * possible that the map explicitly maps the key to {@code null}.
     * The {@link #containsKey containsKey} operation may be used to
     * distinguish these two cases.
     *
     * @see #put(Object, Object)
     */
    public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
    }

Internal array of Hashmap as fixed size and if we are adding more elements into the map, we will get same bucket location for other objects at some point of time. i.e same bucket will return for two different keys and it will store both Map.Entry objects in same bucket. In this case it uses LinkedList inside the same bucket to store the entry objects. i.e it will store new entry object in next node of same bucket.

If we try to retrieve elements from collision bucket, we require one more check to get correct value and it uses equals() method on key value to return correct entry object.  If we get one bucket from key hashing mechanism and if t has two nodes for two entry objects and if we want to get correct entry, Hashmap compares the entry key Object using equals() method and if it return true, then map returns corresponding entry object.

Overridden of value if key is duplicate: Consider below hashmap sample:

package com.sample.java.testing;

import java.util.HashMap;

public class HashMapTest {

    public static void main(String[] args) {

        HashMap hashMap = new HashMap<>();
        hashMap.put("Course", "Java");
        hashMap.put("Course", "J2EE");
        hashMap.put("Course", "Spring");
        hashMap.put("Subject", "Servlet");
        System.out.println(hashMap);
    }

}

Here we will get output as {Course=Spring, Subject=Servlet} because Course Key will override all previous values. Why because all entries will be stored ad linked list if hashcode bucket is same for multiple keys and in that case it uses key.equals("Course") method on keys to inserting/retrieving data. Hence it replace the old values as equals() method will give true if key is same.

Null as Key: If we put null as key in Hashmap it will go to first index of table i.e 0th bucket because hashcode of null is Zero.


Singleton Design Pattern in JAVA

From name Singleton, this pattern restricts the object instantiate and ensures it have only one instance of class is available in JVM and it has below characteristics.

1. Singleton pattern object instantiate and ensures it have only one instance of class is available in JVM.
2. Class should have global access to provide the instance of object.
3. Most commonly used singleton pattern is for Logging in java application.

We have different approaches to implement singleton design pattern and should follow below common points.

1. Constructor should be private so that we other classes can not create object using constructor.
2. Class should have one public static variable to hold the instance of class.
3. Class should have public static method to return the object of class. Application should get the instance of class by using this method. Hence this method should have global access across application.

Singleton Early initiation:

 In this approach object of class in created when it is loaded even client is not request for this object.

package com.sample.java.testing;

public class SingletonEagerInitiationTest {

    public static SingletonEagerInitiationTest eagerInitiationTest = new SingletonEagerInitiationTest();

    private SingletonEagerInitiationTest() {

    }

    public static SingletonEagerInitiationTest getInstance() {
        return eagerInitiationTest;
    }
}

But generally we should avoid object creation early until unless  some other classes required it. And also we do not perform any exception handling.

Static block initiation

In this approach we can provide object creation using static block with exception handling.
package com.sample.java.testing;

public class SingletonStaticInitiationTest {

    public static SingletonStaticInitiationTest initiationTest;

    private SingletonStaticInitiationTest(){
      
    }
  
    static {
        try {
            initiationTest = new SingletonStaticInitiationTest();
        } catch (Exception e) {
            System.out.println("failed to initialize object" + e);
        }
    }

    public static SingletonStaticInitiationTest getInstance() {
        return initiationTest;
    }
}

In this approach also object will initialize early even any other classes are not accessed to this object. We can void this by using Lazy Initiation.

In lazy initiation approach, it won't create object while class loading. It will create object and returns when any other class accessed getInstance() method.


package com.sample.java.testing;

public class SingletonLazyInitiationTest {

    public static SingletonLazyInitiationTest singletonLazyInitiationTest;

    private SingletonLazyInitiationTest() {

    }

    public static SingletonLazyInitiationTest getInstance() {

        try {
            if (singletonLazyInitiationTest == null) {
                singletonLazyInitiationTest = new SingletonLazyInitiationTest();
                return singletonLazyInitiationTest;
            } else {
                return singletonLazyInitiationTest;
            }
        } catch (Exception e) {
            System.out.println("failed to initialize object" + e);
            return null;
        }
    }
}

Here if we are using multiple threads, and two different threads are trying to access the
getInstance() method, it will breaks the singleton pattern. Hence we should follow below approach in multi thread environment by making  getInstance() method as synchronized.

package com.sample.java.testing;

public class SingletonSyncronizedIntitiationTest {

    public static SingletonSyncronizedIntitiationTest singletonSyncronizedIntitiationTest;

    private SingletonSyncronizedIntitiationTest() {

    }

    public static synchronized SingletonSyncronizedIntitiationTest getInstance() {

        try {
            if (singletonSyncronizedIntitiationTest == null) {
                singletonSyncronizedIntitiationTest = new SingletonSyncronizedIntitiationTest();
                return singletonSyncronizedIntitiationTest;
            } else {
                return singletonSyncronizedIntitiationTest;
            }
        } catch (Exception e) {
            System.out.println("failed to initialize object" + e);
            return null;
        }
    }
}



Here even if multiple threads can not get access to getInstance() method as it is synchronized. But it will impact on performance.

String Vs String Buffer Vs String Builder

String is very important and most commonly used object in java programming and we should know some important features of String as a java developer. Here we will some of the important features of string and how it is different from String builder and String buffer.

String:
  • String class is represents as characters ans we can create string object as 
               String s ="java" or String s =new String("java");
  • When we create String with double quotes, first it will check whether same string is available in string pool or not and based on it;s existence, it will create new string in pool or return existing reference. This approach will save lot of memory by using same string  for multiple threads. But here if we go for new operator to create string object, it will create new memory in heap memory. Every string created with new operator will create memory in heap.
  • String is immutable in java and we can share it to different functions , classes and threads safely and String is final class and fields also are final except hashcode .
  • Two string are equal only when both strings have same characters in same order. And String equals() method is case sensitive. We can go for equalsIgnoreCase() if we do not want to check for case sensitive.
String Vs String Buffer Vs String Builder

Since String is immutable object and if we perform operation like concat() and assign it to existing string, it will create new string and delete the old string for Garbage Collection.

        String string1 = "java";
        string1.concat("wleomce");
        System.out.println(string1);// it will print javaonly
        but if we do below
        string1 = string1.concat("language");
        System.out.println(string1);// it will print java language and it deletes "java" literal

So if we do these operation on string, will create lot of garbage on heap. Hence Java provided StringBuilder and StringBuffer classes to manipulate the strings.

Both StringBuilder and StringBuffer are mutable objects and we can perform append(), delete(), subString() etc methods on string object.

StringBuilder vs StringBuffer

1. Thread Safety : Both are mutable classes but StringBuilder is synchronized and all method are synchronized. String builder provided thread safety but it effects on performance. Hence java provided new class StringBuffer in JDKversion 5. StringBuffer is similar to String builder but it omits thread safety and it is not synchronized. Hence we can use StringBuilder in single thread environment else use StringBuffer.

2. Performance: Due to synchronization and thread safety, StringBuffer is less efficient on performance when compared to StringBuilder.

package com.sample.java.testing;

public class StringBuilderTest {

    public static void main(String[] args) {

        String s = "java";
        StringBuilder builder = new StringBuilder(s);
        builder.append(" is OOP language");
        System.out.println(builder.toString());//java is OOP language
    }

}

package com.sample.java.testing;

public class StringBufferTest {

    public static void main(String[] args) {

        String s ="Welcome to java";
        StringBuffer buffer = new StringBuffer(s);
        buffer.delete(0, 10);
        System.out.println(buffer);// java
    }

}

Below are some of basic differences in between String , StringBuffer and StringBuilder

  • String is immutable class where as StringBuffer and StringBuilder are mutable classes.
  • StringBuffer is thread Safe and StringBuilder is not thread safe
  • String Builder class is useful to manipulate String in single thread environment where as StringBuffer will be useful to manipulate String in multi thread environment as it is thread safe.

Monday, 12 March 2018

Comparator Vs Comparable interface in java

Both Comparator and Comparable interfaces provide features to sort the collections of Objects. However java provided some default methods to sort primitive types arrays and array of objects etc using .sort() method etc, we will use Comparator and comparable interfaces  to sort collections.

We will get all details how to use Comparable and Comparator interfaces in my previous posts. Here we can find some basic differences between Comparable and Comparator interface.

1.  Sorting : We can sort in single way  with Comparable Interface. like we can apply sorting with one of the property of bean to sort list of beans.

@Override
    public int compareTo(EmployeeComparableClass o) {
        return this.getId() - o.getId(); // compare based on id
    }

We can sort collection of objects in different ways using Comparator interface. We can write our custom comparator classes and can use different properties to sort the collections.

//compare and sort based on emp is
@Override
    public int compare(EmployeeClass o1, EmployeeClass o2) {
        return o1.getId() - o2.getId();
    }

or

//compare and sort based on emp name
    @Override
    public int compare(EmployeeClass o1, EmployeeClass o2) {
        return o1.getName().compareTo(o2.getName());
    }

2. Implements: Class needs to implement Comparable class  in order to sort.
Class no need to do any implement if we go for Comparator. We can crate new comparator classes by implementing the comparator interfaces.

To sort employee, we need to implement Comparable interface as shown below.
public class EmployeeComparableClass implements Comparable<EmployeeComparableClass>

It is not required if we go for Comparator interface.

3. Package: Comparable interface is available under java.lang package where as Comparator interface is available in java.util package

4.Code changes: We no need to do any code changes from client side if we go for Arrays.sort(), Collections.sort() and Comparable interfaces. Here these will use compareTo() method automatically.

We need to do code changes at client side if we go for Comparator interface.  Here Client needs to provide comparator class to use compare() method.

Ex: Detailed example is available @Comparable and Comparator

Sorting method

int[] numbers = new int[] { 1, 6, 3, 8, 9 };
        System.out.println("without sort " + Arrays.toString(numbers));
        Arrays.sort(numbers);
        System.out.println("sort array " + Arrays.toString(numbers));

Comparator:

List<EmployeeClass> employess = new ArrayList<>();
        employess.add(employeeClass3);
        employess.add(employeeClass2);
        employess.add(employeeClass1);
        employess.add(employeeClass);
        System.out.println("before comarator sorting....");
        for (EmployeeClass employeeClass4 : employess) {
            System.out.println(employeeClass4.toString());// no order it will print emp details randomly
        }
       
        System.out.println("after comarator sorting using emp name....");
        Collections.sort(employess, new ComparatorNameTest());

Comparable:
EmployeeComparableClass[] classes = new EmployeeComparableClass[4];
       
        EmployeeComparableClass employeeClass = new EmployeeComparableClass(60, "Java", 345678);
        EmployeeComparableClass employeeClass1 = new EmployeeComparableClass(50, "J2ee", 9876543);
        EmployeeComparableClass employeeClass2 = new EmployeeComparableClass(30, "Spring", 12345);
        EmployeeComparableClass employeeClass3 = new EmployeeComparableClass(40, "Jdbc", 654);
        classes[0] = employeeClass;
        classes[1] = employeeClass3;
        classes[2] = employeeClass2;
        classes[3] = employeeClass1;
        // below it will throw an runtime exception
        //Exception in thread "main" java.lang.ClassCastException: com.sample.java.testing.EmployeeClass cannot be cast to java.lang.Comparable
        //hence  EmployeeComparableClass implement Comparable interface
        //SO by using comparable we can sort the list based on
        System.out.println("sorting list as per comparable...");
        Arrays.sort(classes);
        for (EmployeeComparableClass course : classes) {
            System.out.println(course.toString());// sorting based on id
        }

Comparable interface in JAVA

Java.lang.Comparable is an interface in java to order/sorting the elements of a user defined class. This has below method

1. public int compareTo(Object o1) -- Compares this object with specified object  for order and returns negative or sero or positive value as this object is less than or equal or greater than the specified object

package com.sample.java.testing;

public class EmployeeComparableClass implements Comparable<EmployeeComparableClass>{
   
    private int id;
    private String name;
    private double salary;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
   
    public String toString() {
        return "Id of employee is " + this.id + " name of emloyess "  + this.name + " salary is " + this.salary;
    }

    public EmployeeComparableClass(int id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }


    /*@Override
    public int compareTo(EmployeeComparableClass o) {
        return o.getName().compareTo(o.getName());// compare based on name
    }*/
   
    @Override
    public int compareTo(EmployeeComparableClass o) {
        return this.getId() - o.getId(); // compare based on id
    }

}

package com.sample.java.testing;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class SortPrimitiveTest {

    public static void main(String[] args) {

        int[] numbers = new int[] { 1, 6, 3, 8, 9 };
        System.out.println("without sort " + Arrays.toString(numbers));
        Arrays.sort(numbers);
        System.out.println("sort array " + Arrays.toString(numbers));

        String[] strings = new String[] { "java", "jdbc", "spring", "servlets",
                "jsp" };
        System.out.println("without sort string array "
                + Arrays.toString(strings));
        Arrays.sort(strings);
        System.out.println("sort string array " + Arrays.toString(strings));

        List<String> courses = new ArrayList<>();
        courses.add("spring");
        courses.add("java");
        courses.add("jsp");
        courses.add("servlets");
        System.out.println("list without sort..");
        for (String string : courses) {
            System.out.println(string);// no sorting
        }
       
        Collections.sort(courses);
       
        System.out.println("list sorted..");
        for (String string : courses) {
            System.out.println(string);// sorting
        }
        EmployeeComparableClass[] classes = new EmployeeComparableClass[4];
       
        EmployeeComparableClass employeeClass = new EmployeeComparableClass(60, "Java", 345678);
        EmployeeComparableClass employeeClass1 = new EmployeeComparableClass(50, "J2ee", 9876543);
        EmployeeComparableClass employeeClass2 = new EmployeeComparableClass(30, "Spring", 12345);
        EmployeeComparableClass employeeClass3 = new EmployeeComparableClass(40, "Jdbc", 654);
        classes[0] = employeeClass;
        classes[1] = employeeClass3;
        classes[2] = employeeClass2;
        classes[3] = employeeClass1;
        // below it will throw an runtime exception
        //Exception in thread "main" java.lang.ClassCastException: com.sample.java.testing.EmployeeClass cannot be cast to java.lang.Comparable
        //hence i EmployeeComparableClass implement Comparable interface
        //SO by using comparable we can sort the list based on
        System.out.println("sorting list as per comparable...");
        Arrays.sort(classes);
        for (EmployeeComparableClass course : classes) {
            System.out.println(course.toString());// sorting based on id
        }

    }

}


Output:

without sort [1, 6, 3, 8, 9]
sort array [1, 3, 6, 8, 9]
without sort string array [java, jdbc, spring, servlets, jsp]
sort string array [java, jdbc, jsp, servlets, spring]
list without sort..
spring
java
jsp
servlets
list sorted..
java
jsp
servlets
spring
sorting list as per comparable...
Id of employee is 30 name of emloyess Spring salary is 12345.0
Id of employee is 40 name of emloyess Jdbc salary is 654.0
Id of employee is 50 name of emloyess J2ee salary is 9876543.0
Id of employee is 60 name of emloyess Java salary is 345678.0

We can sort collection in single way based on one of the attribute using Comparable Interface

Comparator in JAVA

Java.util.Comparator is an interface in java to order/sorting the elements of a user defined class. This has 2 methods

1. public int compare(Object o1, Object o2) -- Compare it's two arguments for order and return a negative integer,  zero or positive integer  as first argument is less than or equal to or greater than second element.
2. public equals(Object o) --- Indicated whether some other object is equal to this comparator.


package com.sample.java.testing;

import java.util.Comparator;

public class ComparatorNameTest implements Comparator<EmployeeClass> {

    //compare and sort baed on emp name
    @Override
    public int compare(EmployeeClass o1, EmployeeClass o2) {
        return o1.getName().compareTo(o2.getName());
    }

}


package com.sample.java.testing;

import java.util.Comparator;

public class ComparatorIdTest implements Comparator<EmployeeClass> {

    @Override
    public int compare(EmployeeClass o1, EmployeeClass o2) {
       return o1.getId() - o2.getId();
    }

}


package com.sample.java.testing;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class EmployeeClass {

    private int id;
    private String name;
    private double salary;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getSalary() {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }
   
    public String toString() {
        return "Id of employee is " + this.id + " name of emloyess "  + this.name + " salary is " + this.salary;
    }

    public EmployeeClass(int id, String name, double salary) {
        this.id = id;
        this.name = name;
        this.salary = salary;
    }

}

package com.sample.java.testing;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ComparatorDemoTest {

    public static void main(String a[]) {
        EmployeeClass employeeClass = new EmployeeClass(60, "Java", 345678);
        EmployeeClass employeeClass1 = new EmployeeClass(50, "J2ee", 9876543);
        EmployeeClass employeeClass2 = new EmployeeClass(30, "Spring", 12345);
        EmployeeClass employeeClass3 = new EmployeeClass(40, "Jdbc", 654);

        List<EmployeeClass> employess = new ArrayList<>();
        employess.add(employeeClass3);
        employess.add(employeeClass2);
        employess.add(employeeClass1);
        employess.add(employeeClass);
        System.out.println("before comarator sorting....");
        for (EmployeeClass employeeClass4 : employess) {
            System.out.println(employeeClass4.toString());// no order it will print emp details randomly
        }
       
        System.out.println("after comarator sorting using emp name....");
        Collections.sort(employess, new ComparatorNameTest());
       
        for (EmployeeClass employeeClass4 : employess) {
            System.out.println(employeeClass4.toString());//  order by emp name it will print emp details based  on name asc order
        }
       
        System.out.println("after comarator sorting using emp id....");
        Collections.sort(employess, new ComparatorIdTest());
       
        for (EmployeeClass employeeClass4 : employess) {
            System.out.println(employeeClass4.toString());//  order by emp name it will print emp details based on id asc order
        }
    }

}



Output:

before comarator sorting....
Id of employee is 40 name of emloyess Jdbc salary is 654.0
Id of employee is 30 name of emloyess Spring salary is 12345.0
Id of employee is 50 name of emloyess J2ee salary is 9876543.0
Id of employee is 60 name of emloyess Java salary is 345678.0
after comarator sorting using emp name....
Id of employee is 50 name of emloyess J2ee salary is 9876543.0
Id of employee is 60 name of emloyess Java salary is 345678.0
Id of employee is 40 name of emloyess Jdbc salary is 654.0
Id of employee is 30 name of emloyess Spring salary is 12345.0
after comarator sorting using emp id....
Id of employee is 30 name of emloyess Spring salary is 12345.0
Id of employee is 40 name of emloyess Jdbc salary is 654.0
Id of employee is 50 name of emloyess J2ee salary is 9876543.0
Id of employee is 60 name of emloyess Java salary is 345678.0


We can sort collections in different ways based on parameter which we want using comparator interface.

List Vs Set in Java

We have Set and List interfaces in Java and we have implemented class like ArrayList and HashSet in Java Collections framework.

It is one of most conman and important java interview question and it is important fundamental concept to remember while dealing with collection.

We will see some of the differences in between set and list

1. Duplicates: This is basic and primary difference between set and List.  List allows duplicates where as Set does not allow Duplicates. Why because Set overrides/replace  the value if we insert duplicates.

2. Sorting Order : List is an ordered collection and will follow insertion order i.e  elements add first will get lower index value than later added. Set does not maintain any order. However we have Sorted set interface which follow some order based on compactor/comparable. Here set uses equals() method to check uniqueness for an element stored in set and SortedSet uses compare() method to sort the elements. Hence equals() and compare()  must be consistent each other in order to maintain proper behavior of elements in set and sorted set.

3. Arraylist is the popular implementation of List interface and HashSet and TreeSet is the popular implementation of Set interface.

When to use which collection: Based on above mentioned differences, we can go for List if we need insertion order and if our collection can contain duplicates or   we can go for set if our collection should have unique elements.

package com.sample.java.testing;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.mail.internet.NewsAddress;

public class ListVsSetDemo {

    public static void main(String[] args) {
      
        System.out.println("list example.............");
        List<String> courses = new ArrayList<>();
        courses.add("java");
        courses.add("j2ee");
        courses.add("spring");
        courses.add("servlets");
        courses.add("java");//allow duplicate and print it
      
        for(String course: courses){
            System.out.println(course);//insertion order
        }
      
        System.out.println("set example.............");
        Set<String> courses2 = new HashSet<>();
        courses2.add("java");
        courses2.add("j2ee");
        courses2.add("spring");
        courses2.add("servlets");
        courses2.add("java");// it will allow but it override previous value with this value
      
        for(String course: courses2){
            System.out.println(course);// no insertion order
        }
      
        System.out.println("treeset example.............");
        Set<String> courses3 = new TreeSet<>();
        courses3.add("java");
        courses3.add("j2ee");
        courses3.add("spring");
        courses3.add("jdbc");
        courses3.add("servlets");
        courses3.add("java");// it will allow but it override previous value with this value
      
        for(String course: courses3){
            System.out.println(course);// follow ascending insertion order
        }
      
        System.out.println("get list from set ans sort example.............");
        List<String> setList = new ArrayList<>(courses);
        Collections.sort(setList);
      
        for(String course: courses3){
            System.out.println(course);// follow ascending insertion order
        }

    }

}

Output:
list example.............
java
j2ee
spring
servlets
java
set example.............
servlets
j2ee
java
spring
treeset example.............
j2ee
java
jdbc
servlets
spring
get list from set ans sort example.............
j2ee
java
jdbc
servlets
spring