Introduction: HashTable , Hash table is basically an array of Lists. Each List is known as a bucket. The position of a bucket is identified by calling the hashcode() method. A Hashtable contains values based on the key.
Hashtable Features:
- The underlying data structure for HashTable is HashTable itself.
- Insertion order is not preserved and it is based on Hashcode of keys.
- Duplicate keys are not allowed but values can be duplicated.
- Heterogeneous objects are allowed for both keys and values.
- ‘null’ is not allowed for both keys and values, if we try to insert ‘null’ we will get runtime exception saying ‘NullPointerException’.
- It implements Serializable and Clonable interfaces but not Random Access.
- Every method present in HashTable is Synchronized and hence HashTable object is ThreadSafe.
- HashTable is the best choice if our frequent operation is search operation.
Constructors of HashTable:
In order to create Hashtable objects, we need to know about Hashtable’s constructors. There are four constructors in Hashtable.
1) Hashtable ht = new Hashtable()
This constructor creates an empty Hashtable object with default initial capacity 11 and default fill ration 0.75.
2) Hashtable ht = new Hashtable(int Initial_Capacity)
This constructor creates an empty Hashtable with an initial capacity specified by Initial_Capacity and with default fill ration 0.75.)
3) Hashtable ht = new Hashtable(int Initial_Capacity, float Fill_Ratio)
This constructor creates an empty Hashtable with an initial capacity specified by Initial_Capacity and with fill ration specified by Fill_Ratio.
4) Hashtable ht = new Hashtable(Map m)
This constructor is used for internal conversion of any Map object to Hashtable object.
Let’s take an example of Hashtable with a small code:
import java.util.*; // Importing module or library class HashtableDemo // Creating main class { public static void main(String[] args) // Main method { Hashtable ht = new Hashtable(); // Creating Hashtable object with initial capacity 11 // and fill ratio 0.75 by default ht.put(5,"A"); // Inserting element in bucket ht.put(4,"B"); // Inserting element in bucket ht.put(3,"C"); // Inserting element in bucket ht.put(2,"D"); // Inserting element in bucket ht.put(1,"E"); // Inserting element in bucket ht.put(0,"F"); // Inserting element in bucket // Printing Hashtable object to see it's elements in buckets System.out.println(ht); } }
The output we will get is:
// After copilation Note: HashtableDemo.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. //We are getting these warnings due to generics // After executing {5=A, 4=B, 3=C, 2=D, 1=E, 0=F}
Now let’s take another example:
import java.util.*; class Test // Test class { int i; // Test class's instance variable Test(int i) // Test class's constructor { this.i=i; // Initializing instance variable } public int hashcode() // overriden hashcode() method to determine hashcode of keys { return i; // Whatever is the value we provide as a key that itself will be the hashcode of key } public String toString() // Overriden toString() method { return i+""; } } class HashtableDemo { public static void main(String[] args) // Main method() { Hashtable ht = new Hashtable(); // Creating empty Hashtable object with default initial capacity and fill ratio ht.put(new Test(5),"A"); // Inserting element into Hashcode object ht.put(new Test(2),"B"); // Inserting element into Hashcode object ht.put(new Test(6),"C"); // Inserting element into Hashcode object ht.put(new Test(15),"D"); // Inserting element into Hashcode object ht.put(new Test(23),"E"); // Inserting element into Hashcode object ht.put(new Test(16),"F"); // Inserting element into Hashcode object //Printing Hashcode object System.out.println(ht); } }
When we run this code we will get the following output:
# After Compilation Note: HashtableDemo2.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. # We get these warnings due to generics # After Running {6=C, 16=F, 5=A, 15=D, 2=B, 23=E}
Let me explain the output.
At first, when we create the empty Hashtable object, a new Hashtable object with 11 empty buckets was created. Then for the first insertion, hashcode of the key 5 was 5 itself (as we have override the hashcode() method in Test class), so the key-value pair 5=A was saved in the 5th bucket in the Hashtable object. In the same way, 2nd and 3rd insertion were done in 2nd and 6th bucket respectively. Now in the 4th case of insertion, the key value is 15, so the value should be inserted in the 15th bucket. But there are 11 buckets only, so 15 is divided by 11 and the remainder is taken as the bucket number, so the key-value pair will be saved in 15%11=4th bucket. Here we have to keep one thing in mind while storing the key-value pair in the bucket, it will be stored as 15=”D”, not 4=”D”. Same for the insertion, 23 will be divided by 11 and the remainder (23%11=1) will be taken, so the key-value pair will be saved in the 1st bucket as 23=”E”. In the last case, we will get the bucket number 5 (as 16%11=5), note that there is already one element present in bucket no 5. But in Hashtable, we can store multiple objects in one bucket. So the last key-value pair will also be saved in bucket 5 as 16=”F”. Now while printing Hashtable object, elements in the buckets will be printed from top to bottom order. Now if there is more than one element in a bucket then those elements will be printed from right to left order. That’s why in our case the output is: {6=C, 16=F, 5=A, 15=D, 2=B, 23=E}.
Properties File in Java:
In our program, if anything which changes frequently (like username, password, mail-id, mobile number etc.) are not recommended to hard code in Java program because if there is any change to reflect that change recompilation, rebuild and redeployment of application is required, even sometimes server restart also required, which creates a big business impact to the client.
We can overcome this problem by using the Properties file. Such type of variable things (like username, password, mail-id, mobile number etc.) we have to configure in the properties file. From that properties file we have to read into Java program, and we can use those properties. The main advantage of this approach is if there is a change in the properties file, to reflect that change just redeployment is enough which won’t create any business impact to the client.
We can use Java Properties object to hold properties which are coming from the Properties file.
In the normal map (like HashMap, Hashtable, TreeMap) key and value can be of any type, but in the case of Properties – key and value should be of String type.
Properties File Constructor:
- Properties p = new Properties()
Properties File Methods:
- String setProperty(String prname, String prvalue) – This method is used to create a new Property. If the specified property already available then old value will be replaced with the new value and returns the old value.
- String getProperty(String prname) – This method is used to get the value associated with the specified property. If the specified property not available then this method returns ‘null’.
- Enumeration propertyName() – This method returns all property names present in Properties object.
- void load(InputStream is) – This method is used to load properties from the Properties file into Java Properties object.
- void store(OutputStream os, String comment) – This method is used to store properties from Java Properties object into the properties file.
Now let us take a simple example for Properties:
At first, say our properties file looks like shown below:
Rajesh=5659 Souvik=2528 Sudarshan=4546
Now, see the code below:
import java.util.*; import java.io.*; class PropDemo { public static void main(String[] args) throws Exception { Properties p = new Properties(); FileInputStream fis = new FileInputStream("xyz.properties"); p.load(fis); System.out.println(p); String s = p.getProperty("Rajesh"); System.out.println(s); p.setProperty("Rahul","8589"); FileOutputStream fos = new FileOutputStream("xyz.properties"); p.store(fos,"Updated by RAJESH"); } }
Here we are importing java.util package as Properties class is present in util package and we are importing java.io package as we have to complete file input-output operations. Next in main() method we are creating Properties class object. Then we are opening an input stream in order to read data from file and we are loading all properties from the properties file into java Property object. Then we are printing the Property object. Next, we are getting the value associated with the property key “Rajesh” and storing the value in the String object s, and we are printing s as well. Then, we are setting the value of the key “Rahul” by 8589, so a new key (“Rahul”) with the given value will be added in the properties file. Next, we are creating an output stream in order to write changes into the properties file. At last, we are writing all changes in the properties file.
Now if we run the code we will get the following output:
- In the terminal:
{Rajesh=5659, Souvik=2528, Sudarshan=4546} 5659
- In properties file:
#Updated by RAJESH #Mon Apr 30 20:29:54 IST 2018 Rahul=8589 Rajesh=5659 Souvik=2528 Sudarshan=4546
Properties is so much important concept in Java that you can’t except completing a single Java project without Properties.
That’s all with Properties and Hashtable in Java . Hope you will be benefited by this tutorial.