Key Concepts:
Hashing
- HashMap uses a hash function to map keys to their respective buckets.
- A good hash function generates a unique hash code for each key, but collisions can still occur. The hash map in Java does not maintain insertion order.
Performance
- HashMap provides constant-time performance (O(1)) for get() and put() operations.
- Performance can degrade to O(n) in the worst case, especially if there are many hash collisions.
Key and Value Types
- HashMap allows any non-null object as a key and any object (including null) as a value.
- For a class to be used as a key, it must implement the equals() and hashCode() methods.
Iteration:
- HashMap provides methods like keySet(), values(), and entrySet() for iterating over key-value pairs.
- The entrySet() method returns a Set view of key-value pairs, allowing iteration and modification.
Thread Safety
- HashMap is not thread-safe. For thread-safe operations, use ConcurrentHashMap.
HashMaps in Java - Pet Registry Example
public class Pet {
private final String name;
private final int age;
private final String color;
public Pet(String name, int age, String color) {
this.name = name;
this.age = age;
this.color = color;
}
public String getName() {
return this.name;
}
public int getAge() {
return this.age;
}
public String getColor() {
return this.color;
}
}
public class PetsRegistry {
private HashMap<String, Pet> petRegistry = new HashMap<>();
public PetsRegistry() {
// Add some pets to the registry
petRegistry.put("Leo", new Pet("Lion", 8, "Gold"));
petRegistry.put("Porky", new Pet("Pig", 3, "Pink"));
petRegistry.put("Ro-Ro", new Pet("Robin", 7, "Red"));
petRegistry.put("Midnight", new Pet("Cat", 10, "Black"));
petRegistry.put("Hobbes", new Pet("Kitty", 1, "Calico"));
petRegistry.put("Duke", new Pet("Dog", 14, "Brown"));
}
public Pet removePet(String name) {
// Remove a pet by name
return petRegistry.remove(name);
}
public void printRegistry() {
// Iterate over the registry and print pet information
for (String name : petRegistry.keySet()) {
Pet pet = petRegistry.get(name);
System.out.println(name + " is a " + pet.getColor() + " " + pet.getName() +
" and is " + pet.getAge() + " years old.");
}
System.out.println();
}
public static void main(String[] args) {
// Initialize the pet registry
PetsRegistry petsRegistry = new PetsRegistry();
petsRegistry.printRegistry();
// Remove a pet
String petNameToRemove = "Hobbes";
Pet removedPet = petsRegistry.removePet(petNameToRemove);
if (removedPet == null) {
System.out.println(petNameToRemove + " not found");
} else {
System.out.println("Removed: " + petNameToRemove + ", " + removedPet);
}
// Print the updated registry
petsRegistry.printRegistry();
}
}
PetsRegistry.main(null)
Hobbes is a Calico Kitty and is 1 years old.
Leo is a Gold Lion and is 8 years old.
Porky is a Pink Pig and is 3 years old.
Ro-Ro is a Red Robin and is 7 years old.
Duke is a Brown Dog and is 14 years old.
Midnight is a Black Cat and is 10 years old.
Removed: Hobbes, REPL.$JShell$16E$Pet@63b16b54
Leo is a Gold Lion and is 8 years old.
Porky is a Pink Pig and is 3 years old.
Ro-Ro is a Red Robin and is 7 years old.
Duke is a Brown Dog and is 14 years old.
Midnight is a Black Cat and is 10 years old.
Example 2 - Student Registry
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
public class Student {
private final int id;
private final String name;
private final int age;
public Student(int id, String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return id == student.id &&
age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(id, name, age);
}
}
public class StudentRegistry {
private final Map<Integer, Student> studentMap = new HashMap<>();
public StudentRegistry() {
// Add some students to the registry
studentMap.put(1, new Student(1, "Alice", 20));
studentMap.put(2, new Student(2, "Bob", 22));
studentMap.put(3, new Student(3, "Charlie", 21));
}
public Student getStudent(int studentId) {
return studentMap.get(studentId);
}
public void printRegistry() {
// Iterate over the registry and print student information
for (Map.Entry<Integer, Student> entry : studentMap.entrySet()) {
int id = entry.getKey();
Student student = entry.getValue();
System.out.println("Student ID: " + id + ", Name: " + student.getName() + ", Age: " + student.getAge());
}
}
}
// Instantiate and use the StudentRegistry class
StudentRegistry studentRegistry = new StudentRegistry();
studentRegistry.printRegistry();
Student ID: 1, Name: Alice, Age: 20
Student ID: 2, Name: Bob, Age: 22
Student ID: 3, Name: Charlie, Age: 21
Popcorn HACK 1
import java.util.HashMap;
import java.util.Map;
public class HashMapTest {
public static void main(String[] args) {
// Create a new HashMap with Integer keys and String values
Map<Integer, String> myMap = new HashMap<>();
// Add some key-value pairs to the HashMap
myMap.put(1, "Apple");
myMap.put(2, "Banana");
myMap.put(3, "Cherry");
// Fill in the blanks: Retrieve and print the value for key 2
String valueForKey2 = myMap.get(___);
System.out.println("Value for key 2: " + valueForKey2);
// Fill in the blanks: Check if the HashMap contains key 4
boolean containsKey4 = myMap.containsKey(___);
System.out.println("Does the map contain key 4? " + containsKey4);
// Fill in the blanks: Remove the entry with key 1 from the HashMap
myMap.remove(___);
// Print the updated contents of the HashMap
System.out.println("Updated HashMap:");
for (Map.Entry<Integer, String> entry : myMap.entrySet()) {
System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
}
}
}
Popcorn HACK 2 - Quiz
Multiple Choice:
Question 1: Hashing in HashMap
What is the primary purpose of a hash function in a HashMap?
- A) To encrypt the keys
- B) To map keys to corresponding buckets
- C) To validate the keys
- D) To generate random numbers
Question 2: Performance of HashMap
What is the time complexity of the get() and put() operations in a well-distributed HashMap?
- A) O(log n)
- B) O(n)
- C) O(1)
- D) O(n^2)
Free Response:
Question 3: Key and Value Types in HashMap
Describe the types of objects that can be used as keys and values in a HashMap. Additionally, explain the methods that a class should implement if used as a key.
Question 4: Iteration in HashMap
Provide brief explanations for two methods in HashMap that can be used to iterate over its key-value pairs.
Question 5: Thread Safety in HashMap
Explain why HashMap is not thread-safe and what issues might arise when multiple threads access the same HashMap instance concurrently. Suggest an alternative class that can be used for concurrent access and explain its benefits.