Lesson 2
Creating an Address Book Application with Kotlin MutableMap
Introduction

Welcome! Today, we will explore creating a simple address book application using Kotlin's collections, specifically mutable maps. This task will help you understand how to manipulate maps in Kotlin, focusing on adding, retrieving, and deleting entries. By the end of this lesson, you'll have a solid grasp of these fundamental operations.

Introducing Methods to Implement

In this task, we will implement three methods to manage our address book:

  • addContact(name: String, phoneNumber: String): Boolean: Adds a new contact. Returns false if the contact already exists, otherwise adds the contact and returns true. In this task, let's assume phone numbers do not change, so it's not allowed to overwrite the existing contact's number.
  • getContact(name: String): String?: Retrieves the phone number for a given name. Returns null if the contact does not exist.
  • deleteContact(name: String): Boolean: Deletes a contact with the given name. Returns true if the contact exists and is deleted; false otherwise.

Let's break down each method in detail in the next sections.

Step 1: Implementing `addContact`

This method adds a new contact to the address book with the given name and phoneNumber. If the contact already exists, it returns false. Otherwise, it adds the contact and returns true.

Question: Why do you think we need to check if the contact already exists?

Answer: To avoid duplicating existing entries. If a contact with the same name already exists, we shouldn't allow overwriting its phone number in this method, as it's only for creation.

Here is the method implementation:

Kotlin
1class AddressBook { 2 val contacts = mutableMapOf<String, String>() 3 4 fun addContact(name: String, phoneNumber: String): Boolean { 5 if (contacts.containsKey(name)) { 6 return false 7 } 8 contacts[name] = phoneNumber 9 return true 10 } 11} 12 13// Example usage: 14fun main() { 15 val addressBook = AddressBook() 16 println(addressBook.addContact("Alice", "123-456-7890")) // true 17 println(addressBook.addContact("Alice", "098-765-4321")) // false 18 println(addressBook.contacts) // {Alice=123-456-7890} 19}

In this method:

  • We verify if the contact already exists using containsKey(name).
  • If it exists, we return false.
  • If it doesn't exist, we add it to our map and return true.
Step 2: Implementing `getContact`

This method retrieves the phone number associated with a given name. If the contact does not exist, it returns null.

Question: What do we gain by returning null when a contact doesn't exist?

Answer: It provides a clear indicator that the contact is not in the address book, allowing us to handle such cases gracefully.

Here is the method implementation:

Kotlin
1class AddressBook { 2 /* Other methods and properties omitted for brevity */ 3 4 fun getContact(name: String): String? { 5 return contacts[name] 6 } 7} 8 9// Example usage: 10fun main() { 11 val addressBook = AddressBook() 12 addressBook.addContact("Alice", "123-456-7890") 13 println(addressBook.getContact("Alice")) // 123-456-7890 14 println(addressBook.getContact("Bob")) // null 15}

In this method:

  • We use the index operator contacts[name] to retrieve the phone number.
  • This returns null if the name doesn't exist in the map.
Step 3: Implementing `deleteContact`

This method deletes a contact with the given name. If the contact exists and is deleted, it returns true. If the contact does not exist, it returns false.

Question: What could be a real-world consequence of not checking if the contact exists before deletion?

Answer: Attempting to delete a non-existent contact could result in errors or unintended behavior.

Here is the method implementation:

Kotlin
1class AddressBook { 2 /* Other methods and properties omitted for brevity */ 3 4 fun deleteContact(name: String): Boolean { 5 return if (contacts.containsKey(name)) { 6 contacts.remove(name) 7 true 8 } else { 9 false 10 } 11 } 12} 13 14// Example usage: 15fun main() { 16 val addressBook = AddressBook() 17 addressBook.addContact("Alice", "123-456-7890") 18 println(addressBook.deleteContact("Alice")) // true 19 println(addressBook.deleteContact("Bob")) // false 20 println(addressBook.contacts) // {} 21}

In this method:

  • We verify if the contact exists using containsKey(name).
  • If it exists, we remove it using remove(name) and return true.
  • If the contact doesn't exist, we return false.
Why Kotlin's Maps are Efficient for These Tasks

Kotlin's maps, particularly MutableMap, provide several benefits for managing an address book:

  • Efficient Lookups: Maps offer a fast average time complexity for lookups. This means retrieving a contact's phone number by name is efficient, even with a large set of contacts.
  • Uniqueness: Maps ensure that keys (in this case, contact names) are unique, preventing duplicate entries and simplifying data integrity management.
  • Readability: The syntax for accessing map entries is clear and concise, making the code easy to read and maintain.
  • Null Safety: Kotlin’s type system allows us to explicitly handle nullable values, making it easier to work with potentially missing data and reducing runtime errors.

These characteristics make Kotlin's MutableMap a suitable choice for implementing an address book.

Lesson Summary

In this lesson, we created a simple address book application using Kotlin's collections, specifically MutableMap. We implemented methods to add, retrieve, and delete contacts. Each step was built upon the previous one, enhancing our understanding of manipulating maps in Kotlin. Happy coding!

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