Lesson 4
Managing Employee Records with Nested Maps and Lists in Java
Managing Records with Nested Maps and Lists in Java

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.

Introducing Methods to Implement

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 returns false. Otherwise, it adds the project and returns true.
  • 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 returns false. If the task is added successfully, it returns true.
  • 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 returns null. 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 returns null.
Step 1: Basic Class Structure

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.

Java
1import 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.

Step 2: Implementing the Traverse Method

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:

Java
1import 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.

Step 3: Implementing AddProject Method

We'll implement the addProject method and provide all necessary components for it to be executable.

Java
1import 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.

Step 4: Implementing AddTask Method

We'll next implement the addTask method, along with all components needed for it to be executable.

Java
1import 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.

Step 5: Implementing GetTasks Method

Lastly, we'll implement the getTasks method, along with all necessary components for it to be executable.

Java
1import 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.

Lesson Summary

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.

Enjoy this lesson? Now it's time to practice with Cosmo!
Practice is how you turn knowledge into actual skills.