Saturday, 28 June 2014

What is Dependency Injection in Spring ? Explain DI types and advantages with examples

             Dependency Injection (DI) in Spring is a design pattern used to achieve Inversion of Control (IoC) between classes and their dependencies. It allows objects to be loosely coupled by injecting the dependencies from the outside rather than creating them internally.

            The basic concept of the Inversion of Control pattern  is that you do not create your objects but describe how they should be created. You don't directly connect your components and services together in code but describe which services are needed by which components in a configuration file. A container (in the case of the Spring framework, the IOC container) is then responsible for hooking it all up. In a typical IOC scenario, the container creates all the objects, wires them together by setting the necessary properties, and determines when methods will be invoked.  
    
        There are two types of DI,
  • Setter Injection
  • Constructor Injection                                                                 

Setter Injection:-

    Spring framework will inject the dependency via a setter method.
XML configuration for setter Dependency Injection is below.

  <bean id="classBean" class="com.adnjava.ClassBean">
     <!-- setter injection using the nested <ref/> element -->
       <property name="studentBean"><ref bean="studentBean"/></property>
  </bean>
  <bean id="studentBean" class="com.adnjava.StudentBean"/> 

         The ClassBean java POJO class is as below,

 package com.adnjava;

  public class ClassBean {

       private StudentBean studentBean;

       public void setStudentBean(StudentBean studentBean){
           this.studentBean=studentBean;
       }

       public void getStudentBean(){
             return studentBean;
       }
 }

 Constructor Injection:-

          Here Spring uses the  Constructor and the arguments passed to it to determine the dependency. Rest all is same as setter injection.
     
      XML configuration for
Constructor Dependency Injection is below.


  <bean id="classBean" class="com.adnjava.ClassBean">
       <constructor-arg><ref bean="studentBean"/></constructor-arg>
      <!--OR you can use <constructor-arg ref="yetAnotherBean"/>-->
  </bean>
  <bean id="studentBean" class="com.adnjava.StudentBean"/>  

         The ClassBean java POJO class is as below,

 package com.adnjava;
  
  public class ClassBean {

         private StudentBean studentBean;

         public ClassBean(StudentBean studentBean){
              this.studentBean=studentBean;
         }

         public void getStudentBean(){
               return studentBean;
         }
  }


              Interface Injection:

             This is not implemented in Spring currently, but by Avalon. It’s a different type of DI that involves mapping items to inject to specific interfaces.

Advantages Of Dependency Injection:

  • Loosely couple code
  • Separation of responsibility
  • Configuration and code is separate.
  • Using configuration, you can provide implemented code  without changing the dependent code.
  • Testing can be performed using mock objects.

Related Post:--
Spring MVC workflow with example  
Spring MVC with Hibernate CRUD Example  
Spring Annotations  

Friday, 27 June 2014

Bean Lifecycle in Spring Framework

            The Spring Framework is based on the Inversion of Control (IoC) principle, which is why it is often referred to as an IoC container. Spring beans reside within the IoC container and are managed by it. A Spring bean is simply a Plain Old Java Object (POJO) that is instantiated, configured, and managed by the Spring container.

The following steps explain the lifecycle of a Spring bean within the container.
  1. The container looks for the bean definition in the configuration file (e.g., beans.xml).
  2. Using the Reflection API, the container creates the bean object. If any properties are defined in the bean definition, the container also injects and initializes those properties.
  3. If the bean implements the BeanNameAware interface, the factory calls setBeanName() passing the bean’s ID.
  4. If the bean implements the BeanFactoryAware interface, the factory calls setBeanFactory(), passing an instance of itself.
  5. If there are any BeanPostProcessors associated with the bean, their post- ProcessBeforeInitialization() methods will be called before the properties for the Bean are set.
  6. If an init() method is specified for the bean, it will be called.
  7. If the Bean class implements the DisposableBean interface, then the method destroy() will be called when the Application no longer needs the bean reference.
  8. If the Bean definition in the Configuration file contains a 'destroy-method' attribute, then the corresponding method definition in the Bean class will be called.

Sunday, 22 June 2014

Why Doesn't the Map Interface Extend the Collection Interface in Java?

 The main reason is that Map and Collection represent two different data models.
  • A Collection represents a group of individual elements.

  • A Map represents key-value pairs (mappings).

Because of this fundamental difference, the Map interface does not extend the Collection interface.

Why doesn't Map extend Collection?

1. A Collection stores only elements

A Collection interface (implemented by List, Set, and Queue) stores a group of individual objects.

List<String> names = List.of("John", "David", "Smith");

Here, each item is a single element.

2. A Map stores key-value pairs

A Map stores data in the form of keys and values.

Map<Integer, String> employees = new HashMap<>();

employees.put(101, "John");
employees.put(102, "David");
employees.put(103, "Smith");

Each entry consists of a key and its corresponding value.

3. Duplicate handling is different

Collection

  • List allows duplicate elements.

  • Set does not allow duplicate elements.

Map

  • Keys must be unique.

  • Values can be duplicated.

Map<Integer, String> map = new HashMap<>();

map.put(1, "Java");
map.put(2, "Java");   // Allowed (duplicate value)
map.put(1, "Spring"); // Replaces the previous value for key 1


4. Their operations are completely different

Collection methods work with elements.

add(E e)
remove(Object o)
contains(Object o)

Map methods work with key-value mappings.

put(K key, V value)
get(Object key)
remove(Object key)
containsKey(Object key)
containsValue(Object value)
Because their APIs are fundamentally different, inheritance would not make sense.

5. A Map can expose collections when needed

Although a Map is not a Collection, it provides methods that return collections of its contents.

map.keySet();      // Returns Set<K>
map.values();      // Returns Collection<V>
map.entrySet();    // Returns Set<Map.Entry<K, V>>

Example:

Map<Integer, String> map = new HashMap<>();
map.put(1, "Java");
map.put(2, "Spring");

Set<Integer> keys = map.keySet();
Collection<String> values = map.values();
Set<Map.Entry<Integer, String>> entries = map.entrySet();

Collection vs Map

CollectionMap
Stores individual elementsStores key-value pairs
Represents a group of objectsRepresents mappings between keys and values
Uses methods like add() and remove()Uses methods like put() and get()
Implemented by List, Set, and QueueImplemented by HashMap, TreeMap, LinkedHashMap, etc.
Elements may or may not be unique (depending on implementation)Keys must be unique; values may be duplicated



Related Posts:--
1) How HashMap works internally in Java?
2) Internal Implementation of TreeMap in Java
3) Internal implementation of ArrayList in Java
4) Collection Interview Questions and Answers in Java
5) Internal Implementation of LinkedList in Java
6) Collection Hierarchy in Java

Saturday, 21 June 2014

Singleton Design Pattern in Java with Examples

         In this post, we will learn the principles of the Singleton design pattern, explore different ways to implement it, and discuss some best practices for using it.

       The Singleton design pattern restricts the instantiation of a class, ensuring that only one instance of the class exists within the Java Virtual Machine (JVM). A Singleton class provides a global access point through which the single instance of the class can be accessed.

       The Singleton design pattern is commonly used for logging, database driver objects, caching, configuration management, and thread pools. It is also used by several other design patterns, such as Abstract Factory, Builder, Prototype, and Facade.

To implement the Singleton Design Pattern, the following principles should be followed:

  1. Private constructor – Prevents other classes from creating new instances of the class.

  2. Private static instance reference – Holds the single instance of the class and prevents external modification.

  3. Public static method – Provides a global access point to retrieve the Singleton instance.


Below are the different approaches for implementing the Singleton design pattern.

  • Eager initialization

            In eager initialization, the Singleton instance is created when the class is loaded into memory. This is the simplest way to implement the Singleton design pattern. However, it has one drawback: the instance is created even if the client application never uses it, which may result in unnecessary memory usage.
Below is the implementation of the Singleton class using eager initialization.     

  public class EagerInitializer{
        
        private static final EagerInitializer instance = new EagerInitializer();

        //private constructor to avoid client applications to use constructor.
        private  EagerInitializer(){
        }
        public static EagerInitializer getInstance(){
              return instance;
        }
  }

           If your Singleton class does not consume many resources, eager initialization is a suitable approach. However, in most real-world scenarios, Singleton classes are used to manage resource-intensive objects such as file systems, database connections, or configuration managers. In such cases, it is better to delay the creation of the instance until the client invokes the getInstance() method.

Another limitation of eager initialization is that it does not provide flexibility for handling exceptions that may occur during instance creation.

  • Static block initialization

            The static block initialization approach is similar to eager initialization, except that the Singleton instance is created inside a static initialization block. This approach provides the flexibility to handle exceptions that may occur during instance creation.

 public class StaticInitializer {
        private static StaticInitializer instance ;
        //private constructor to avoid client applications to use constructor.
        private  StaticInitializer() {
        }
        static {
             try {
                 instance = new StaticInitializer();
             } catch(Exception e) {
                     throw new RuntimeException("Exception in static block");
             }
        }
        public static StaticInitializer getInstance() {
               return instance;
        }
 }

          Both eager initialization and static block initialization create the Singleton instance before it is actually needed. In many cases, this is not considered a best practice because the instance is created even if it is never used. In the following sections, we'll explore how to implement a Singleton class that supports lazy initialization.

  • Lazy Initialization

            The lazy initialization approach creates the Singleton instance only when it is requested through the global access method (getInstance()). This ensures that the instance is created only when it is actually needed.

Below is a sample implementation of the Singleton design pattern using the lazy initialization approach.


  public class LazyInitializer{

        private static LazyInitializer instance;

        //private constructor to avoid client applications to use constructor.
        private  LazyInitializer(){
        }
        public static LazyInitializer getInstance(){
              if(instance == null){
                       instance = new LazyInitializer();
              }
              return instance;
        }
  }

        The above implementation works well in a single-threaded environment. However, in a multithreaded environment, it can cause issues if multiple threads enter the if block simultaneously. In such a scenario, multiple instances of the Singleton class may be created, violating the Singleton design pattern and causing different threads to obtain different instances.

In the next section, we'll explore different approaches for implementing a thread-safe Singleton class.

  • Thread Safe Singleton

       The simplest way to make a Singleton class thread-safe is to synchronize the global access method (getInstance()). This ensures that only one thread can execute the method at a time, preventing multiple instances from being created concurrently.

A typical implementation of this approach is shown below.


  public class ThreadSafe{

        private static ThreadSafe instance ;
                        
        //private constructor to avoid client applications to use constructor.
        private  ThreadSafe(){
        }

        public static synchronized ThreadSafe getInstance(){
               if(instance == null){
                     instance = new ThreadSafe();
               }
               return instance;
         }
  }

         The above implementation is thread-safe and works correctly. However, it can reduce performance because every call to the getInstance() method requires synchronization, even after the Singleton instance has already been created. In practice, synchronization is only needed when the instance is created for the first time.

To avoid this unnecessary synchronization overhead, the Double-Checked Locking pattern is used. In this approach, the instance is checked before entering the synchronized block and checked again inside the synchronized block. This ensures that synchronization occurs only during the initial creation of the Singleton instance while maintaining thread safety.

The following code snippet demonstrates the Double-Checked Locking implementation.


                 public static ThreadSafe getInstance(){
                          if(instance == null){
                                    synchonized(ThreadSafe.class){
                                             if(instance == null ){
                                                      instance = new ThreadSafe();
                                             }
                                     }
                           }
                           return instance;
                 }


JDBC Example using Singleton Design pattern:--

          A common real-world example of the Singleton design pattern is a ConnectionFactory class. This class is implemented as a Singleton and contains the database connection configuration along with methods for creating database connections.

The reason for making the ConnectionFactory class a Singleton is that only one instance of the factory is required throughout the application. This single factory instance can then be used to create multiple database Connection objects whenever needed—one factory, many connections.


package com.adnjavainterview;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class ConnectionFactory {
           //static reference to itself
         private static ConnectionFactory instance = new ConnectionFactory();
         public static final String URL = "jdbc:mysql://localhost/jdbcdb";
         public static final String USER = "YOUR_DATABASE_USERNAME";
         public static final String PASSWORD = " YOUR_DATABASE_PASSWORD";
         public static final String DRIVER_CLASS = "com.mysql.jdbc.Driver";
              //private constructor
         private ConnectionFactory() {
                 try {
                        Class.forName(DRIVER_CLASS);
                  }
                  catch (ClassNotFoundException e) {
                        e.printStackTrace();
                  }
         }
    
         private Connection createConnection() {
                   Connection connection = null;
                   try {
                          connection = DriverManager.getConnection(URL, USER, PASSWORD);
                   }
                   catch (SQLException e) {
                           System.out.println("ERROR: Unable to Connect to Database.");
                   }
                   return connection;
         } 
    
         public static Connection getConnection() {
                 return instance.createConnection();
         }
 }

Thank you for visiting blog..

Related Post:--

Thursday, 19 June 2014

Why Doesn't the Set Interface Allow Duplicate Elements in Java?

       If you have 3+ years of Java experience, an interviewer may ask this question to test your understanding of how a Set works internally in Java.

Internally, a HashSet stores its elements using a HashMap. A HashMap stores data as key-value pairs, whereas a Set contains only unique elements. When an element is added to a HashSet, it is stored as the key in the underlying HashMap, and a constant dummy object is used as the value for every entry.

Since HashMap does not allow duplicate keys, HashSet also does not allow duplicate elements. If you attempt to add a duplicate element, the add() method returns false, and the element is not added to the Set.

When a new element is added successfully, the add() method returns true. If the element already exists, it returns false. Therefore, adding a duplicate element does not result in a compile-time or runtime error—it is simply ignored.



Related Posts:--
1) How HashMap works internally in Java?
2) Internal Implementation of TreeMap in Java
3) Internal implementation of ArrayList in Java
4) Collection Interview Questions and Answers in Java
5) Internal Implementation of LinkedList in Java
6) Collection Hierarchy in Java

Wednesday, 18 June 2014

Difference Between a Web Server and an Application Server

       A Web Server is responsible for handling HTTP requests and serving static web content, such as HTML, CSS, JavaScript, and images. An Application Server provides an environment for running business logic and generating dynamic content. It can process client requests, interact with databases, execute business logic, and return dynamic responses.

Web Server

A web server primarily serves static resources and forwards dynamic requests to an application server if needed.

Responsibilities:

  • Serves static content (HTML, CSS, JavaScript, images, PDFs, etc.)

  • Handles HTTP/HTTPS requests

  • Supports SSL/TLS termination

  • Performs URL rewriting and request routing

  • Can act as a reverse proxy and load balancer

Examples:

  • Apache HTTP Server

  • Nginx

  • Microsoft IIS


Application Server

An application server executes the application's business logic and generates dynamic content.

Responsibilities:

  • Executes Java, .NET, or other server-side applications

  • Processes business logic

  • Connects to databases

  • Manages transactions and security

  • Generates dynamic responses

  • Supports technologies such as Servlets, JSP, EJB, and REST APIs

Examples:

  • Apache Tomcat

  • JBoss EAP

  • IBM WebSphere Application Server

  • Oracle WebLogic Server


Key Differences

FeatureWeb ServerApplication Server
PurposeServes static web contentExecutes business logic and serves dynamic content
ContentStatic (HTML, CSS, JS, images)Dynamic (JSP, Servlets, REST APIs, business logic)
Database AccessNoYes
Business LogicNoYes
Transaction ManagementNoYes
Security FeaturesBasicAdvanced
Enterprise ServicesNoYes
ExamplesApache HTTP Server, Nginx, IISTomcat, WildFly, WebLogic, WebSphere

In Spring Boot

With Spring Boot, the distinction is often less visible because it includes an embedded servlet container such as Apache Tomcat by default. This allows you to package and run your application without installing a separate application server.

For production environments, many organizations still place a web server such as Nginx or Apache HTTP Server in front of the Spring Boot application to handle SSL termination, load balancing, caching, and reverse proxying.

Monday, 16 June 2014

What Is a Marker Interface in Java? Why Do We Need It?

            A marker interface in Java is an interface that does not declare any fields or methods. In other words, an empty interface is known as a marker interface.

Some common examples of marker interfaces are Serializable, Cloneable, and Remote.

Since a marker interface does not define any fields, methods, or behavior, you might wonder why Java needs it. The purpose of a marker interface is to provide metadata to the JVM or frameworks, indicating that a class possesses a particular capability or should receive special handling during runtime.


What Is the Purpose of a Marker (Tag) Interface in Java

If you look closely at marker interfaces in Java, such as Serializable, Cloneable, and Remote, you'll notice that they are used to indicate a special capability or characteristic of a class to the JVM or framework.

For example, when the JVM detects that a class implements Serializable, it enables Java's serialization mechanism for that class. Similarly, if a class implements Cloneable, the JVM allows the Object.clone() method to create a field-by-field copy of the object. In the case of RMI, implementing the Remote interface indicates that the object can be invoked remotely.

In short, a marker interface serves as a marker that provides metadata to the JVM or framework, indicating that the class should receive special handling.

A common interview follow-up question is: "Why not use a boolean flag or a String field inside the class instead of a marker interface?"

Although the same information could be represented using a boolean flag or a String, marker interfaces offer several advantages. They make the purpose of a class more explicit and readable, enable compile-time type checking, and allow APIs to leverage polymorphism by accepting only objects that implement a particular marker interface. These benefits make marker interfaces a cleaner and more object-oriented design choice.


   Where Should I use Marker interface in Java :--

            Apart from the built-in marker interfaces such as Serializable and Cloneable, you can also create your own marker interfaces. A marker interface is a good way to logically classify your code. By creating custom marker interfaces, you can group related classes and, if you have your own framework or tool, perform pre-processing or special operations on the classes that implement those interfaces. Marker interfaces are particularly useful when developing APIs and frameworks.

However, since the introduction of annotations in Java 5, annotations have become a better alternative to marker interfaces in many scenarios. JUnit is a perfect example of this approach, where the @Test annotation is used to identify test methods. The same functionality could have been achieved using a Test marker interface, but annotations provide a more flexible and expressive solution.


      Another use Of Marker Interface in Java:


            Another use of marker interfaces in Java is to communicate design intent. For example, a marker interface named ThreadSafe can be used to indicate to other developers that any class implementing this interface is expected to be thread-safe. Any future modifications to such classes should preserve this thread-safety guarantee.

Marker interfaces can also be used by custom code analysis, code coverage, or code review tools to identify classes with specific behavior and perform additional validation. However, since the introduction of annotations in Java 5, annotations have become a better choice for these use cases. For example, using a @ThreadSafe annotation is much more expressive and flexible than implementing a ThreadSafe marker interface.

Is Runnable a Marker Interface?

A common interview question is whether the Runnable interface is a marker interface.

The answer is No. Runnable is not a marker interface because it declares the public void run() method. A marker interface does not contain any methods or fields.

Can We Create Our Own Marker Interface?

Another frequently asked question is whether we can create our own marker interface.

The answer is Yes. Although we cannot make the JVM treat a custom marker interface the same way it treats built-in marker interfaces such as Serializable or Cloneable, we can create our own marker interfaces and implement custom logic around them. For example, a framework or utility can check whether a class implements a particular marker interface and perform specific processing based on that.

Summary

In summary, marker interfaces in Java are used to indicate special behavior or metadata to the compiler, JVM, frameworks, or custom tools. However, since Java 5, annotations have become the preferred approach because they are more expressive, flexible, and easier to use than marker interfaces in most scenarios.

Why character array is preffered to store Password than String?


        Strings are immutable in Java if you store password as plain text it will be available in memory until Garbage collector clears it and since String are used in String pool for reusability there is pretty high chance that it will be remain in memory for long duration, which pose a security threat. Since any one who has access to memory dump can find the password in clear text and that's another reason you should always used an encrypted password than plain text. Since Strings are immutable there is no way contents of Strings can be changed because any change will produce new String, while if you char[] you can still set all his element as blank or zero. So Storing password in character array clearly mitigates security risk of stealing password.

        With Strings there is always a risk of printing plain text in a log file or console  but if use Array you won't print contents of the array instead its memory location get printed, though not a real reason but make but still make sense.
      For Example,
                            class PassCharArrEx {
                                   public static void main(String args[]) {
                                           String pass = "password_of_blog";
                                           System.out.println("String="+pass);
                                           char chpass[] = "password_of_blog".toCharArray();
                                           System.out.println("Character="+chpass);
                                    }
                            }
Output :
                    String=password_of_blog
                    Character=$%(Q($_#(QQ#


How HashMap works internally in Java?

                One of the most important question of the core java interviewers is How hash map works in java or internal.implementation of hashmap. Most of the candidates rejection chances increases if the candidate do not give the satisfactory explanation . This question shows that candidate has good knowledge of Collection . So this question should be in your to do list before appearing for the interview .
                 HashMap works on the principle of Hashing .  To understand Hashing , we should understand the three terms first   i.e  Hash Function , Hash Value and Bucket .

     What is Hash Function , Hash Value  and Bucket ?


         The hashCode() function  which returns an integer value is the Hash function. The important point to note that ,  this method is present in Object class ( Mother of all class ) .
       
        This is the code for the hash function(also known as hashCode method) in Object Class :

    public native int hashCode();

      The most important point to note from the above line :  hashCode method return  int value .
So the Hash value is the int value returned by the hash function .

      What is bucket ?

           
          A bucket is used to store key value pairs . A bucket can have multiple key-value pairs . In hash map, bucket used simple linked list to store objects .
           
          Before start with internal working of HashMap,first you should know this thing,

  1. Two unequal object may return same hashcode.
  2.  When two objects are equal by equals(), then they must have same hashcode.  

      There are two main  methods used for storing and retrieving values from HashMap.

1) .put() method to put /store values in HashMap
2) .get() method to retrieve data/values from HashMap

1) How put(Key key, Value v) method works internally?


 Lets see implementation of put method:

public V put(K key, V value) {
      if (key == null)
         Nreturn 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;
 }

Let us understand above code step by step,

1) Key object is checked for null. If key is null then it will be stored at table[0] because hashcode for
    null is always 0.
2) Key object’s hashcode() method is called and hash code is calculated. This hashcode is used to find
    index of array for storing Entry object. It may happen sometimes that, this hashcode function is
   poorly written so JDK designer has put another function called hash() which takes above calculated
    hash value as argument.
3) indexFor(hash,table.length)  is used to calculate exact index in table array for storing the Entry
    object.
      The indexFor will return the index of table array, the index calculation is based on hashcode of key and length of table array. This will do the and operation as ,
 
 static int indexFor(int h, int length) {
    return h & (length-1);
 }
 
4) If two key objects have same hashcode(which is known as collision) then it will be stored in form
    of linkedlist.So here, we will iterate through our linkedlist.


  2) How get(Key key) method works internally?

        
       Here are the steps, which happens, when you call get() method with key object to retrieve corresponding value from hash based collection.
     
    Let's see code,

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

1) Key object is checked for null. If key is null then value of Object resides at table[0] will be returned.
2) Key object’s hashcode() method is called and hash code is calculated.
3) indexFor(hash,table.length)  is used to calculate exact index in table array using generated hashcode for getting the Entry object.
4) After getting index in table array, it will iterate through linkedlist and check for key equality by calling equals() method and if it returns true then it returns the value of Entry object else returns null.

What happens if two keys has same hashCode?


           If multiple keys has same hashCode, then during put() operation collision had occured, which means multiple Entry object stored in a bucket location. Each Entry keep track of another Entry, forming a linked list data structure. Now , if we need to retrieve value object in this situation, following steps will be followed :

1) Call hashCode() method of key to find bucket location.
2) Traverse  through linked list, comparing keys in each entries using keys.equals() until it return true. So, we use equals() method of key object to find correct entry and then return value from that.
       

Key Notes:--

1) Data structure to store Entry objects is an array named table of type Entry.

2) A particular index location in array is referred as bucket, because it can hold the first element of a LinkedList of Entry objects.

3) Key object’s hashCode() is required to calculate the index location of Entry object.

4) Key object’s equals() method is used to maintain uniqueness of Keys in map.

5) Value object’s hashCode() and equals() method are not used in HashMap’s get() and put() methods.

6) Hash code for null keys is always zero, and such Entry object is always stored in zero index in Entry[].



Related Posts:-- 
1) Internal Implementation of TreeMap in Java  
2) How to iterate the TreeMap in reverse order in Java  
3) Java Program to Count Occurrence of Word in a Sentence  
4) Internal implementation of ArrayList in Java  
5) String Interview Questions and Answers
6) Exception Handling Interview questions and answers

Why String is immutable or final in java?

            This is an old yet still popular question. There are multiple reasons that String is designed to be immutable in Java. A good answer depends on good understanding of memory, synchronization, data structures, etc. In the following, I will summarize some answers.

  • Requirement of String Pool

             String pool (String intern pool) is a special storage area in Java heap. When a string is created and if the string already exists in the pool, the reference of the existing string will be returned, instead of creating a new object and returning its reference.
The following code will create only one string object in the heap.
                   
            String s1="nrk infotech";
            String s2="nrk infotech";

           If string is not immutable, changing the string with one reference will lead to the wrong value for the other references.

  • Allow String to Cache its Hashcode

               The hashcode of string is frequently used in Java. For example, in a HashMap. Being immutable guarantees that hashcode will always the same, so that it can be cashed without worrying the changes.That means, there is no need to calculate hashcode every time it is used. This is more efficient.

             String s1="one";
             HashMap<String,Integer>  map =  new HashMap<String,Integer>();
             map.put(s1,new Integer(1));
             s1.concat("two");
             System.out.println(map.get(s1));

    Immutable objects are much better suited to be Hashtable keys.

For example,
                                    
    
In the above code,s1 value won't change whenever you are calling map.get(s1) so it will work properly.
 
 For Example ,in case of StringBuffer,

                 StringBuffer s1=new StringBuffer("one");
              HashMap<String,Integer>  map =  new HashMap<String,Integer>();
              map.put(s1,new Integer(1));
              s1.append("two");
              System.out.println(map.get(s1));     //here s1=onetwo

 In the above code it will return null.
                 
  •  Security

           String is widely used as parameter for many java classes, e.g. network connection, opening files, etc. Were String not immutable, a connection or file would be changed and lead to serious security threat. The method thought it was connecting to one machine, but was not. Mutable strings could cause security problem in Reflection too, as the parameters are strings.

  • Thread Safety

                 Immutable objects are thread-safe. Two threads can both work on an immutable object at the same time without any possibility of conflict. No external synchronization is required.
 

Related Post:--
1) What are the immutable classes in java?&how to create immutable class& what are the conditions?
2) String Related interview questions & Answers