- Project: Hash Maps
We are here to broaden your exposure to Computer Science. We can only achieve that purpose when you work hard and honestly. It may be tempting to copy-paste code from a classmate, or let a classmate do all your work for you don't! You will be cheating yourself from the most valuable thing course has to offer: overcoming challenges.
We know that hard, and honest work doesn't come easily. If you feel like you are falling behind
- Don't copy-paste code, or let someone do your work for you
- Ask for help!
- Tell the teaching team you need more time
- Open the assignment link your teacher posts in Teams or OneNote, and accept the assignment. GitHub will create a private project just for you.
- On your new project page, click the green Code button, copy the link, and clone the project into IntelliJ (File → New → Project from Version Control, then paste the link).
- When IntelliJ asks if you trust the project, say yes / trust it so it can finish setting things up.
- If IntelliJ asks you to pick a Java version (JDK), choose 17 or newer.
- Use the green play dropdown near the top-right of IntelliJ. You should see options like
Main,CompanyDirectoryArrayListTests,CompanyDirectoryHashMapTests,AllTests, andCompanyDirectoryBenchmarks. You can stay in the file you are editing — you do not need to open a different file first.
If anything looks confusing the first time you open the project, ask a teacher — IntelliJ asks a few one-time setup questions, and then day-to-day work is just writing code and using that green play button.
This project implements a directory of employees at a company. You will write code that implements the directory twice – once using an ArrayList and once using a HashMap. The purpose of implementing the directory twice is to help understand the differences between ArrayLists and HashMaps, and in which situations one may be better than the other.
To help illustrate this, you will also run "benchmarks" to measure the efficiency of the operations for each implementation.
There are three parts of this assignment:
- Write the application code
- Write tests
- Run benchmarks and report findings
The program contains three packages:
main: source code that comprises the application itselftest: tests that ensure the code in themainpackage works as expectedbenchmark: code that times how long various operations take to complete
These classes contain the code for the employee directory application you'll be writing. To run the program, select the "Main" run configuration at the top right corner of the screen and click the green triangle (the "run" button) to the right.
The Employee class represents basic information about an employee at a company. An Employee
instance keeps track of that employee's name and where they work (building name and office number).
You do NOT need to make changes to this class.
The CompanyDirectoryArrayList and CompanyDirectoryHashMap classes both maintain information about
employees at a company. While they implement the same functions described below, they use different
data structures internally. As the names suggest, CompanyDirectoryArrayList and
CompanyDirectoryHashMap maintain employee information in an ArrayList and HashMap, respectively.
You'll need to implement the following functions in both classes:
| Function | Description |
|---|---|
void addEmployee(Employee employee) |
Adds a new employee to the directory. |
Employee findEmployeeByName(String employeeName) |
Finds an existing employee in the directory by their name. |
Employee findEmployeeByOffice(String buildingName, int officeNumber) |
Finds an existing employee in the directory by their office. |
String displayAllEmployees() |
Returns information about all employees (each on its own line). |
HashMap tip: In CompanyDirectoryHashMap, the map is keyed by employee name (see the provided tests that call getAllEmployees().get(name)). Use that key design when you implement add/find — that is what you will compare against the ArrayList version in the benchmarks.
Office tip: findEmployeeByOffice must match both building name and office number (tests include decoys with the same office number in a different building).
Display tip: displayAllEmployees should return one Employee.toString() per line (newline-separated). Main already prints the returned string.
Find tip: If no matching employee exists, return null.
- The
Mainclass serves as the user interface. Themain()method first asks the user if they want to keep track of their employees using an ArrayList or a HashMap. The program will then create aCompanyDirectoryArrayListorCompanyDirectoryHashMapand use it for the duration of the program. - Users can then add employees to the directory, find them by name, find them by their office, or display information about all employees in the directory. The program will run until in a loop until the user decides to quit the program.
- Note that employee information is not maintained between runs of your program. We'd need to leverage file I/O for that!
- You do NOT need to make changes to this class.
- To ensure that the application code works as expected, write tests in
CompanyDirectoryArrayListTestsandCompanyDirectoryHashMapTests; there are run configurations already available to run them. - For details about what each test should do, see the comments / descriptions in the code.
Benchmarking is a process for measuring how your program runs. Benchmarking is can be used to measure the amount of memory your program takes up on the computer, what percentage of the processor's capacity it is utilizing, etc. In our case, we'll be using this technique to measure how long certain operations take for the program to complete.
We leverage the Java Microbenchmark Harness (JMH) to declare and execute our benchmarks.
- In order to execute benchmarks in IntelliJ, you will need to install the JMH plugin. After installing it, restart IntelliJ for the changes to take effect.
- Similar to running tests, there is a run configuration provided for you that will run all the benchmarks. From the drop-down menu in the top-right corner, select the "CompanyDirectoryBenchmarks" configuration and click the green "Play" button to run all the benchmarks.
- Note that running all the benchmarks will take about 5 minutes to complete.
When you run one or more benchmarks, you will see output displays metric from the benchmarks. For example:
# Run complete. Total time: 00:05:14
Benchmark Mode Cnt Score Error Units
MyAwesomeFunction avgt 25 205.127 ± 4.831 us/op
BetterThanAwesomeFunction avgt 25 78.633 ± 5.063 us/op
WorseThanAwesomeFunction avgt 25 839.522 ± 39.274 us/op| Column | Meaning |
|---|---|
| Benchmark | The name of the benchmark that ran. |
| Mode | For us, this will always be avgt, i.e. the benchmark measures the average time per execution. |
| Cnt | The number of times the benchmark ran. |
| Score | The average time it took to execute the function. |
| Error | The margin of error for the measured value. |
| Units | The units of measurement for the "Score" column. |
Once you've written your application code and have ensured it works by writing unit tests, we are ready to run our benchmarks and get results.
We have put a new page for this report in your OneNote in a page called "Project 6: Benchmarks Report"; you should put your hypotheses and results here.
- Before running the benchmarks, consider how the same operations in
CompanyDirectoryArrayListandCompanyDirectoryHashMapmight compare. Based on what you know about how ArrayLists and HashMaps work (at a high level), do you expect one or the other to be faster for a given operation? Do you expect them to be about the same? Why? Record your hypothesis for each kind of operation (addEmployee,findEmployeeByName,findEmployeeByOffice). - Run the benchmarks as described above.
- For each function, put the average time per operation in the table, as reported by the benchmarking process.
- Compare the result for each operation against your hypothesis. Was your hypothesis correct?
Describe the results in a paragraph or two. Were certain operations faster for one implementation
or the other? Did certain operations take similar amounts of time?
- It's ok if any of your hypotheses were incorrect; that's how the scientific method works! Don't change your hypothesis after the fact. Whether or not your hypotheses were correct will not be a factor in your grade, however your explanations will.
There is an additional function updateEmployeeOffice that you can implement for a company directory.
When implemented, it should allow you to change the office location for an employee already in the directory.
Do this for both the ArrayList and HashMap directories and complete the corresponding tests.
Employee does not have setters for building/office — do not add setters. Figure out how to update the directory entry given that constraint.
As mentioned previously, employee information is not persisted when the program stops running. Using file I/O techniques, save employee information to a file when the program ends. Each employee's information should be on its own line in the output file.
For additional credit after implementing the code that writes employee information to an output file, add functionality that will read the same file when the program starts. Make this optional for the user, so that they can always start with a new directory if they so choose.
Create an additional benchmark and report the results. If you decide to do this, ask a teacher to explain more about how to write benchmarks to ensure you do this correctly.
At the end of every class period, commit and push your work from IntelliJ:
- Click Git > Commit… (or use the Commit tool window).
- Review the changed files. You can double-click a file to see the diff.
- Enter a short commit message, then choose Commit and Push….
- Confirm the push to your project's
mainbranch. - On GitHub, confirm your latest commits are visible.
Pushing to main is how you turn in work for this assignment. Autograding runs on those pushes. You can keep improving and pushing after the deadline if your teacher allows late work — ask about any late penalty.
addEmployee() |
5 pts |
findEmployeeByName() |
5 pts |
findEmployeeByOffice() |
5 pts |
displayAllEmployees() |
5 pts |
addEmployee() |
5 pts |
findEmployeeByName() |
5 pts |
findEmployeeByOffice() |
5 pts |
displayAllEmployees() |
5 pts |
| No compile errors | 10 pts |
| Code spaced and indented properly | 10 pts |
| Descriptive variable names | 5 pts |
| Correctly pushed to GitHub | 5 pts |
| Turned in on time | 15 pts |
| Update employee office location | 10 pts |
| Write employee information to a file | 5 pts |
| Read employee information from a file | 5 pts |
| Implement an additional benchmark | 5 pts |
| (not including extra credit) |