Introduction

Welcome to our exploration of Compound Data Structures in Kotlin. Having navigated through Maps, Sets, and Lists, we'll delve into nested maps and lists. These structures enable us to handle complex and hierarchical data, which is typical in real-world scenarios. This lesson will guide you through a recap of the basics, the creation and modification of nested maps and lists, as well as common error handling.

Recap: Maps, Lists, and Understanding Nested Structures

Here's a simple example of a school directory that uses a map with grades as keys and lists of students as values:

Creating Nested Maps and Lists

Just like their non-nested versions, creating nested structures is straightforward. Kotlin's data classes can be leveraged for better organization when needed.

Nested Map:

Nested List:

Lists within a Map:

Accessing Values in Nested Structures

The retrieval of values from nested maps or lists follows rules similar to those for their non-nested counterparts.

From Nested Map:

The notation used to access values from a nested map involves chaining the access operations. Here's a breakdown:

  1. Accessing the Outer Map:

    • nestedMap["fruit"]: This accesses the value associated with the key "fruit" in the outer map. The value is another map (mapOf("apple" to "red", "banana" to "yellow")).
  2. Safe Call Operator (?.):

    • ?. is used to safely access the inner map. If "fruit" does not exist in nestedMap, the expression evaluates to null, preventing a null pointer exception.
  3. Accessing the Inner Map:

    • .get("apple"): This accesses the value associated with the key "apple" in the inner map. The value is "red", which is then printed.

Overall, println(nestedMap["fruit"]?.get("apple")) safely accesses and prints the color of the apple from the nested map structure, outputting "red". From Nested List:

From Both:

Common Operations on these Structures

The modification of nested lists and maps can be done using mutable structures; Kotlin provides mutable variants for altering data.

Identifying Errors and Handling Exceptions

Kotlin provides try/catch blocks for error handling. Below is an example of handling potential null pointer exceptions when accessing nested collections.

In this code block, the try/catch mechanism is used to handle potential exceptions gracefully when accessing a non-existent key in a nested map. Here's how it works:

  1. try Block:

    • The try block encloses the code that might throw an exception.
    • In this case, nestedMap["fruit"]?.get("mango") attempts to access the color of "mango" from the inner map associated with the "fruit" key.
    • Because "mango" does not exist in the map, the expression evaluates to null.
  2. Elvis Operator (?:):

    • ?: is used to handle the case where the expression on the left is null.
    • If the result of nestedMap["fruit"]?.get("mango") is null, the Elvis operator triggers the throwing of a NoSuchElementException with the message "Key not found!".
  3. catch Block:

    • The catch block captures the NoSuchElementException if it is thrown in the try block.
    • Within the catch block, println(e.message) prints the exception message "Key not found!" to the console.

Alternatively, you can use Kotlin's let function combined with the Elvis operator for more elegant error handling:

In this second example, let is employed to safely operate on the non-null color value. If the color is found, it prints a success message and returns the color. If the value is null, the Elvis operator with run provides a fallback, printing an error message and returning a default value. This approach offers a functional way to handle potential null values while maintaining code readability.

This use of error handling allows the program to avoid crashing due to accessing non-existent keys and provides user-friendly feedback instead.

Lesson Summary

Bravo! You've made a journey through nested lists and maps, essential concepts in the data-intensive programming world. We've learned how to create, access, and modify values in these complex structures and how to handle errors.

Up next, we have hands-on practice sessions to solidify your understanding of these concepts. Hold on to your hats!

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal