Welcome! Today, we are going to explore an engaging task that involves managing employee records within a company. Specifically, we will work with nested maps and lists to add projects and tasks for employees and retrieve those tasks as needed. This exercise will help you understand how to manipulate hierarchical data structures efficiently using Java.
Let's start by discussing the methods we will implement in our EmployeeRecords
class.
boolean addProject(String employeeId, String projectName)
- This method adds a new project to an employee's list of projects. If the project already exists for that employee, the method returnsfalse
. Otherwise, it adds the project and returnstrue
.boolean addTask(String employeeId, String projectName, String task)
- This method adds a new task to a specified project for an employee. If the project does not exist for that employee, the method returnsfalse
. If the task is added successfully, it returnstrue
.List<String> getTasks(String employeeId, String projectName)
- This method retrieves all tasks for a specified project of an employee. If the project does not exist for that employee, the method returnsnull
. Otherwise, it returns the list of tasks.List<String> traverse(String employeeId, String projectName)
- This private method helps to locate the nested structure for a given employee and project. If the path is valid and exists, it returns the target list. If it is invalid or does not exist, it returnsnull
.
Now, let's build our EmployeeRecords
class step by step, ensuring we understand each component clearly.
We'll start with the basic structure of the class and initialize our data storage.
Java1import java.util.HashMap; 2import java.util.List; 3import java.util.Map; 4 5class EmployeeRecords { 6 private Map<String, Map<String, List<String>>> records; 7 8 public EmployeeRecords() { 9 records = new HashMap<>(); 10 } 11} 12 13public class Solution { 14 public static void main(String[] args) { 15 EmployeeRecords records = new EmployeeRecords(); 16 System.out.println(records); 17 } 18}
In this initial setup, we define the EmployeeRecords
class and create an instance variable records
that is a nested map. This structure will be used to store employee records, where each key is an employee ID, and each value is another map holding projects and their respective tasks.
The traverse
method helps to locate the nested structure for a given employee and project. If the path is valid and exists, it returns the target list. If the path is invalid or does not exist, it returns null
.
Here is the breakdown of how traverse
works:
Java1import java.util.HashMap; 2import java.util.List; 3import java.util.Map; 4 5class EmployeeRecords { 6 private Map<String, Map<String, List<String>>> records; 7 8 public EmployeeRecords() { 9 records = new HashMap<>(); 10 } 11 12 protected List<String> traverse(String employeeId, String projectName) { 13 if (!records.containsKey(employeeId)) { 14 return null; 15 } 16 Map<String, List<String>> employeeProjects = records.get(employeeId); 17 if (projectName != null && !employeeProjects.containsKey(projectName)) { 18 return null; 19 } 20 return projectName != null ? employeeProjects.get(projectName) : null; 21 } 22} 23 24public class Solution { 25 public static void main(String[] args) { 26 EmployeeRecords records = new EmployeeRecords(); 27 List<String> result = records.traverse("E123", "ProjectA"); 28 System.out.println(result == null ? "No project found." : String.join(", ", result)); 29 } 30}
This method checks if the employeeId
exists in the records
map and optionally checks for a projectName
. If either is invalid, it returns null
.
We'll implement the addProject
method and provide all necessary components for it to be executable.
Java1import java.util.HashMap; 2import java.util.List; 3import java.util.ArrayList; 4import java.util.Map; 5 6class EmployeeRecords { 7 private Map<String, Map<String, List<String>>> records; 8 9 public EmployeeRecords() { 10 records = new HashMap<>(); 11 } 12 13 protected List<String> traverse(String employeeId, String projectName) { 14 if (!records.containsKey(employeeId)) { 15 return null; 16 } 17 Map<String, List<String>> employeeProjects = records.get(employeeId); 18 if (projectName != null && !employeeProjects.containsKey(projectName)) { 19 return null; 20 } 21 return projectName != null ? employeeProjects.get(projectName) : null; 22 } 23 24 public boolean addProject(String employeeId, String projectName) { 25 if (!records.containsKey(employeeId)) { 26 records.put(employeeId, new HashMap<>()); 27 } 28 Map<String, List<String>> employeeProjects = records.get(employeeId); 29 if (employeeProjects.containsKey(projectName)) { 30 return false; 31 } else { 32 employeeProjects.put(projectName, new ArrayList<>()); 33 return true; 34 } 35 } 36} 37 38public class Solution { 39 public static void main(String[] args) { 40 EmployeeRecords records = new EmployeeRecords(); 41 System.out.println(records.addProject("E123", "ProjectA")); // Returns true 42 43 List<String> projectList = records.traverse("E123", "ProjectA"); 44 if (projectList != null) { 45 System.out.println("Project found: " + "ProjectA"); 46 } else { 47 System.out.println("Project not found: " + "ProjectA"); 48 } 49 } 50}
In this implementation, the addProject
method ensures that each employee can have unique projects. It checks if the specified projectName
already exists for the given employeeId
within the records
map. If the project does not exist, it initializes a new entry with an empty list for tasks and returns true
.
We'll next implement the addTask
method, along with all components needed for it to be executable.
Java1import java.util.HashMap; 2import java.util.List; 3import java.util.ArrayList; 4import java.util.Map; 5 6class EmployeeRecords { 7 private Map<String, Map<String, List<String>>> records; 8 9 public EmployeeRecords() { 10 records = new HashMap<>(); 11 } 12 13 private List<String> traverse(String employeeId, String projectName) { 14 if (!records.containsKey(employeeId)) { 15 return null; 16 } 17 Map<String, List<String>> employeeProjects = records.get(employeeId); 18 if (projectName != null && !employeeProjects.containsKey(projectName)) { 19 return null; 20 } 21 return projectName != null ? employeeProjects.get(projectName) : null; 22 } 23 24 public boolean addProject(String employeeId, String projectName) { 25 if (!records.containsKey(employeeId)) { 26 records.put(employeeId, new HashMap<>()); 27 } 28 Map<String, List<String>> employeeProjects = records.get(employeeId); 29 if (employeeProjects.containsKey(projectName)) { 30 return false; 31 } else { 32 employeeProjects.put(projectName, new ArrayList<>()); 33 return true; 34 } 35 } 36 37 public boolean addTask(String employeeId, String projectName, String task) { 38 List<String> project = traverse(employeeId, projectName); 39 if (project == null) { 40 return false; 41 } 42 project.add(task); 43 return true; 44 } 45} 46 47public class Solution { 48 public static void main(String[] args) { 49 EmployeeRecords records = new EmployeeRecords(); 50 records.addProject("E123", "ProjectA"); 51 System.out.println(records.addTask("E123", "ProjectA", "Task1")); // Returns true 52 System.out.println(records.addTask("E123", "NonExistentProject", "Task3")); // Returns false 53 } 54}
In this step, the addTask
method is introduced, which adds a task to a specified project for an employee. By utilizing the traverse
helper method, it checks if the specified project exists under the given employee ID. If the project is present, it adds the task to the project’s task list and returns true
. If the project does not exist, it returns false
.
Lastly, we'll implement the getTasks
method, along with all necessary components for it to be executable.
Java1import java.util.HashMap; 2import java.util.List; 3import java.util.ArrayList; 4import java.util.Map; 5 6class EmployeeRecords { 7 private Map<String, Map<String, List<String>>> records; 8 9 public EmployeeRecords() { 10 records = new HashMap<>(); 11 } 12 13 private List<String> traverse(String employeeId, String projectName) { 14 if (!records.containsKey(employeeId)) { 15 return null; 16 } 17 Map<String, List<String>> employeeProjects = records.get(employeeId); 18 if (projectName != null && !employeeProjects.containsKey(projectName)) { 19 return null; 20 } 21 return projectName != null ? employeeProjects.get(projectName) : null; 22 } 23 24 public boolean addProject(String employeeId, String projectName) { 25 if (!records.containsKey(employeeId)) { 26 records.put(employeeId, new HashMap<>()); 27 } 28 Map<String, List<String>> employeeProjects = records.get(employeeId); 29 if (employeeProjects.containsKey(projectName)) { 30 return false; 31 } else { 32 employeeProjects.put(projectName, new ArrayList<>()); 33 return true; 34 } 35 } 36 37 public boolean addTask(String employeeId, String projectName, String task) { 38 List<String> project = traverse(employeeId, projectName); 39 if (project == null) { 40 return false; 41 } 42 project.add(task); 43 return true; 44 } 45 46 public List<String> getTasks(String employeeId, String projectName) { 47 return traverse(employeeId, projectName); 48 } 49} 50 51public class Solution { 52 public static void main(String[] args) { 53 EmployeeRecords records = new EmployeeRecords(); 54 records.addProject("E123", "ProjectA"); 55 records.addTask("E123", "ProjectA", "Task1"); 56 List<String> tasks = records.getTasks("E123", "ProjectA"); // Returns List<String> with "Task1" 57 if (tasks != null) { 58 System.out.println(String.join(", ", tasks)); // Outputs: Task1 59 } 60 List<String> nonExistentTasks = records.getTasks("E123", "NonExistentProject"); 61 System.out.println(nonExistentTasks == null); // Prints true 62 } 63}
By leveraging the traverse
method, the getTasks
method efficiently locates the target project within the nested map structure. If the project exists, it returns the list of tasks; otherwise, it returns null
. This method exemplifies effective retrieval from hierarchical data structures, allowing easy access to manage employee tasks.
In this lesson, we successfully implemented the EmployeeRecords
class for managing projects and tasks for employees using nested maps and lists in Java. We covered methods for adding projects, adding tasks to those projects, and retrieving tasks from those projects, leveraging the traverse
method to handle nested data efficiently.
Understanding how to work with hierarchical data structures allows you to efficiently manage complex data hierarchies, which enhances your programming skills and problem-solving capabilities. By using Java's HashMap
and ArrayList
, you gain practical experience with dynamic data handling and retrieval techniques.