Hashtable as a data structure
Hashtable is a data structure where data is stored in an array format. Every data value has a unique key value. If the key is known, access to the needed data is very fast. So, insertion and search operations are fast independently on the data size. Hash Table consists of an array to keep data and hashing for generation an index where an element should be located. What is hashing? It is a rule that maps the Object into a set of characters (code). Usually that kind of function converts a big piece of data into a small integer value. Hash functions could be different, but they all submit certain properties:- A particular object has the particular hash code.
- Two equal objects have the same hash codes. The reverse is not true.
- If two hash codes are different, the objects are definitely not equal.
- Different objects may have the same hash code. This very rare event calls collision. The good hash function minimizes probability of collisions.
Hashtable in Java
Hashtable class is the implementation of a hash table data structure. This collection was created earlier than the Java Collection Framework, but was later included in it. Like all “early” collections (from Java 1.0), a hashtable is synchronized (almost all methods are marked as synchronized). Because of this factor, hashtable has significant performance problems. Hence, starting from Java 1.2, in most cases it is recommended to use other implementations of the Map interface due to their lack of synchronization. Usually HashMap is the most appropriate replacement. So Class Hashtable<K,V> consists of keys and values. It stores keys on the principle of hashing. Key-value pairs are stored in "buckets". The buckets together construct a "table", a kind of internal array. Hashtable uses the key’s hashcode to determine a bucket where the key/value pair should map. Hash function lets to get bucket location from Key’s hashcode. This function returns an integer number for an object. As we said above two equal objects have the same hashcode, while two unequal objects might not always have different hashcodes. Different objects, put into a hashtable may have the same hash code. To resolve this problem (collision) array of lists are used in hashtable. The pairs mapped to a single bucket are stored in a list and this list reference is stored in array index.Hashtable Java Constructors
- Hashtable(), the default constructor. It creates an empty hashtable. (Default initial capacity = 11, load factor =0.75).
- Hashtable(int size) constructs a hashtable of specified size.
- Hashtable(int size, float fillRatio) creates hash table of specified size and fill ratio.
- Hashtable(Map m) creates a hashtable with the same mappings as the given Map.
Hashtable Declaration
The Hashtable Java class implements Map, Cloneable and Serializable interfaces. It extends Dictionary class.
Hashtable.java
public class Hashtable<K,V>
extends Dictionary<K,V>
implements Map<K,V>, Cloneable, java.io.Serializable
K is the type of keys maintained by the map.
V is the type of mapped values.
Example:
Hashtable<Student, Integer> myHTable = new Hashtable<>();
How to import hashtable java
Java Hashtable is inside java.util package. So use import java.util.Hashtable; in your code. Usually you will get a hint from your IDE about this.Hashtable main operations
The main operations of the Hashtable is getting, insertion to the collection and removing from there. Here these three operations are:- Object get(Object key) returns the value of the Object that has specified key. Returns null if no such key is found.
- Object put(Object key, Object value) maps the specified key to the specified value. Neither the key nor the value can be null.
- int size() returns the quantity of entries in the hash table.
- boolean contains(Object value) checks if specified value is in the hash table. If so, method returns true, else returns false.
- boolean containsValue(Object value) checks if specified value is in the hash table. If so, method returns true, else returns false.
- void clear() removes all entries from the hashtable.
- boolean containsKey(Object key) returns true if specified key exists in the hash table, else return false.
- boolean isEmpty() returns true if the hashtable is empty or false if it contains at least one key.
- void rehash() increases the size of the hashtable and rehashes all of its keys.
Hash table implementation, Java code:
Let’s create a Student class:
import java.util.Date;
public class Student {
String surname;
String name;
String secondName;
Long birthday; // Long instead of long is used by Gson/Jackson json parsers and various orm databases
public Student(String surname, String name, String secondName, Date birthday ){
this.surname = surname;
this.name = name;
this.secondName = secondName;
this.birthday = birthday == null ? 0 : birthday.getTime();
}
@Override
public int hashCode(){
//TODO: check for nulls
return (surname + name + secondName + birthday).hashCode();
}
@Override
public boolean equals(Object other_) {
Student other = (Student)other_;
return (surname == null || surname.equals(other.surname) )
&& (name == null || name.equals(other.name))
&& (secondName == null || secondName.equals(other.secondName))
&& (birthday == null || birthday.equals(other.birthday));
}
}
Here is Java Hashtable example. Let’s put two Objects of the Student class into hashtable, then remove some and check some parameters.
public class HashTableExample {
public static void main(String[] args) {
Hashtable<Student, Integer> myHTable = new Hashtable<>();
Student sarah1 = new Student("Sarah","Connor", "Jane", null);
Student john = new Student("John","Connor", "Kyle", new Date(1985, 02-1, 28)); // date not exists
myHTable.put(john,1);
myHTable.put(sarah1,0);
System.out.println(myHTable.get(john));
System.out.println(myHTable.isEmpty());
System.out.println(myHTable.size());
System.out.println(myHTable.contains(1));
myHTable.remove(john);
System.out.println(myHTable.contains(0));
System.out.println(myHTable.contains(1));
System.out.println(myHTable.containsKey(sarah1));
}
}
The result of running program is:
1
false
2
true
true
false
true
HashMap vs Hashtable
- Hashtable is similar to HashMap in Java. The most significant difference is that Hashtable is synchronized while HashMap is not. Therefore, Hashtable is slower than HashMap because of synchronization.
- Except of synchronization problem, Hashtable does not allow null to be used as a value or key. HashMap allows one null key and multiple null values.
- Hashtable inherits Dictionary class while HashMap inherits AbstractMap class.
- HashMap is traversed by Iterator. Hashtable can be traversed not only by Iterator but also by Enumerator.
Java hashtable example (Hashtable vs HashMap null key)
Here is a fragment code to demonstrate a null used as a key and value in HashMap and Hashtable
// Null key Java hashtable example and hashmap example
try{
System.out.println("Hashtable");
Hashtable hashTable = new Hashtable();
hashTable.put(null, new Object());
}catch(Exception ex){
ex.printStackTrace();
}
System.out.println("HashMap");
HashMap hashMap = new HashMap();
hashMap.put(null, new Object());
System.out.println("as you see no exceptions with null key in HashMap");
}
The result of running the program that contains this fragment:
java.lang.NullPointerException
at java.base/java.util.Hashtable.put(Hashtable.java:480)
at Character.main(Character.java:58)
HashMap
as you see no exceptions with null key in HashMap
When is Hashtable Beneficial?
The Hashtable
class in Java is a great choice when you need a data structure that allows you to store key-value pairs and requires thread safety. Let’s break this down with some practical scenarios:
Managing a Dictionary of Words and Definitions
Imagine you're building a dictionary app where every word maps to its definition. A Hashtable
is perfect for this because it provides quick lookups and ensures thread safety—so if multiple users are accessing the dictionary at once, it won’t break!
import java.util.Hashtable;
public class DictionaryApp {
public static void main(String[] args) {
Hashtable<String, String> dictionary = new Hashtable<>();
dictionary.put("Java", "A high-level programming language.");
dictionary.put("Hashtable", "A synchronized map for key-value pairs.");
dictionary.put("Thread", "A unit of execution in a program.");
System.out.println("Definition of Java: " + dictionary.get("Java"));
}
}
Output:
Definition of Java: A high-level programming language.
Pretty neat, right? Quick and safe access to data!
Caching Frequently Used Data
Let’s say you’re developing a web application that frequently fetches user data. Storing that data in a Hashtable
allows you to cache it and access it quickly, while also handling concurrent access smoothly.
Tracking Active User Sessions
In a multi-threaded web server, tracking active user sessions can be tricky. Using a Hashtable
ensures that updates to session data are thread-safe without needing to manually synchronize access.
Implications of Using Hashtable
Alright, now let’s talk about the flip side. While Hashtable
can be super useful, it’s important to understand its implications before using it. Let’s break it down.
1. Thread Safety Comes with a Cost
Hashtable
synchronizes every method, meaning only one thread can access it at a time. This is great for thread safety, but it can slow things down in high-performance applications. If you don’t need synchronization, consider using HashMap
for better performance.
2. Null Keys and Values are a No-Go
Unlike HashMap
, Hashtable
doesn’t allow null
keys or values. Trying to put a null
key or value will throw a NullPointerException
. This is something to keep in mind if there’s a chance your data might contain null
values.
Hashtable<String, String> hashtable = new Hashtable<>();
hashtable.put(null, "Oops!"); // Throws NullPointerException
hashtable.put("Oops!", null); // Throws NullPointerException
3. Alternatives for Modern Applications
In most modern Java applications, developers prefer using ConcurrentHashMap
instead of Hashtable
for better scalability and performance in concurrent environments. It’s more efficient because it locks only portions of the map rather than the entire map.
Hashtable vs. HashMap vs. ConcurrentHashMap
Feature | Hashtable | HashMap | ConcurrentHashMap |
---|---|---|---|
Thread Safety | Yes (synchronized) | No | Yes (better scalability) |
Allows null Keys/Values |
No | Yes (1 null key, multiple null values) | No |
Performance | Slower due to full synchronization | Faster in single-threaded contexts | Faster in concurrent contexts |
Preferred Usage | Legacy code, simple thread-safe needs | General-purpose maps | High-concurrency applications |
GO TO FULL VERSION