Exploring Dart Fundamentals - Part 4: Data Structures and Null Safety in Dart

Written by sadanandgadwal | Published 2024/04/19
Tech Story Tags: dart | dart-programming-language | basics | dsa | flutter | null-safety-in-dart | data-structures-in-dart | lists-maps-sets-in-dart

TLDRThis article dives deep into Dart programming, covering data structures like lists, maps, sets, and the crucial aspect of null safety. Understand how to leverage these features to write efficient and reliable Dart code for improved readability and maintainability.via the TL;DR App

Exploring Data Structures and Null Safety Lists, Maps, Maps and Null Safety in Dart

Dart, as a modern programming language, offers robust support for data structures like lists, maps, and sets, along with features such as null safety for writing more secure and predictable code. In this blog post, we’ll delve into the basics of these data structures and explore how Dart’s null safety features enhance code reliability.

1. Lists

Lists in Dart are ordered collections of objects. They are dynamic and can grow or shrink in size.

Let’s explore some basic operations with lists:

void main() { // Create a list of integers named 'marks' with initial values. List<int> marks = [34, 78, 87, 97, 105];

// Add an element '107' to the end of the 'marks' list. marks.add(107);

// Remove the element '105' from the 'marks' list. marks.remove(105);

// Insert the element '30' at index 0 of the 'marks' list. marks.insert(0, 30);

// Output the entire list of 'marks'. print(marks);

// Output the length of the 'marks' list. print("Length is ${marks.length}");

// Output the first element of the 'marks' list. print("First Index is ${marks[0]}");

// Output the last element of the 'marks' list. print("Last Index is ${marks[4]}");

// Join all elements of the 'marks' list into a single string separated by spaces. final join = marks.join(" "); print("Joined method $join");

// Create a string named 'name' with the value "Flutter". String name = "Flutter";

// Split the 'name' string into a list of substrings based on spaces. final split = name.split(" "); print("Split method $split"); }

Here’s what each part does:

  • List<int> marks = [34, 78, 87, 97, 105];: Initializes a list named 'marks' with integers [34, 78, 87, 97, 105].
  • marks.add(107);: Appends the integer 107 to the end of the 'marks' list.
  • marks.remove(105);: Removes the integer 105 from the 'marks' list.
  • marks.insert(0, 30);: Inserts the integer 30 at the beginning (index 0) of the 'marks' list.
  • print(marks);: Outputs the entire list of 'marks'.
  • print("Length is ${marks.length}");: Outputs the length of the 'marks' list.
  • print("First Index is ${marks[0]}");: Outputs the first element of the 'marks' list.
  • print("Last Index is ${marks[4]}");: Outputs the last element of the 'marks' list.
  • final join = marks.join(" ");: Joins all elements of the 'marks' list into a single string separated by spaces.
  • final split = name.split(" ");: Splits the string 'name' into a list of substrings based on spaces.

2. Maps

Maps in Dart represent collections of key-value pairs. They are unordered collections, but the keys are unique within a map.

Here’s how we can work with maps:

void main() { // Create a map named 'person' with string keys and dynamic values. Map<String, dynamic> person = { 'name': 'sadanand', 'age': 23, 'city': "kalaburagi", };

// Access and print values from the 'person' map using keys. print(person['name']); // Prints the value associated with the key 'name'. print(person['age']); // Prints the value associated with the key 'age'. print(person['city']); // Prints the value associated with the key 'city'.

// Add a new key-value pair 'phone' to the 'person' map. person['phone'] = "91-7204832431";

// Output all values of the 'person' map in a single line. print(person.values); }

Here’s what each part does:

  • Map<String, dynamic> person = {...};: Initializes a map named 'person' with string keys and dynamic values. It contains information about a person's name, age, and city.
  • print(person['name']);, print(person['age']);, print(person['city']);: Accesses and prints the values associated with the keys 'name', 'age', and 'city' respectively from the 'person' map.
  • person['phone'] = "91-7204832431";: Adds a new key-value pair 'phone' with the value "91-7204832431" to the 'person' map.
  • print(person.values);: Prints all the values stored in the 'person' map in a single line. The values are retrieved as an iterable using the values property of the map.

3. Sets

Sets in Dart are collections of unique items. They do not allow duplicate elements.

Let’s see how sets work:

void main() { // Create a set named 'numbers' with integer elements. Set<int> numbers = {0,10, 20, 30, 40, 50};

// Output the entire set 'numbers'. print(numbers);

// Create a list named 'marks' with integer elements, including duplicates. List<int> marks = [1,34, 78, 78, 87, 97, 105, 105];

// Create a set named 'uniqueSet' by removing duplicate elements from the 'marks' list. final uniqueSet = Set.of(marks); print(uniqueSet); // Output the unique elements set.

// Create a new list named 'notUniqueList' by copying elements from the 'marks' list. final notUniqueList = List.from(marks); print(notUniqueList); // Output the copied list.

// Iterate over the 'marks' list using a for loop with index. print("Printing marks list using a for loop"); for (int i = 0; i < marks.length; i++) { print(marks[i]); }

// Iterate over the 'marks' list to get every item using a for-in loop. print("Printing marks list to get every item"); for (int mark in marks) { print(mark); } }

Here’s what each part does:

  • Set<int> numbers = {0,10, 20, 30, 40, 50};: Initializes a set named 'numbers' containing integer elements.

  • print(numbers);: Outputs the entire set of 'numbers'.

  • List<int> marks = [1,34, 78, 78, 87, 97, 105, 105];: Initializes a list named 'marks' with integer elements, including duplicates.

  • final uniqueSet = Set.of(marks);: Creates a set named 'uniqueSet' by removing duplicate elements from the 'marks' list.

  • print(uniqueSet);: Outputs the unique elements in the set 'uniqueSet'.

  • final notUniqueList = List.from(marks);: Creates a new list named 'notUniqueList' by copying elements from the 'marks' list.

  • print(notUniqueList);: Outputs the copied list 'notUniqueList'.

  • Iterating over the ‘marks’ list using both a traditional for loop and a for-in loop, printing each element in separate sections.

4. Null Safety in Dart

Dart provides null safety features to prevent null reference errors, which are common in many programming languages.

Here’s how null safety works:

void main() { // Non-nullable variable (will cause an error if used before initialized) int x; print(x); // This line will cause an error because 'x' is not initialized.

// Nullable variable int? y; print(y); // This will print 'null' because 'y' is nullable and not initialized.

int? z = 10; // Nullable variable with an initial value

// Using if-else statement for null check if(z == null) { print("null"); } else { print(z.isEven); // Checks if 'z' is even if it's not null. }

// Null safety operator for concise null checks print(z?.isEven); // Prints whether 'z' is even if 'z' is not null. Otherwise, prints null.

// Null assertion operator (!) for asserting that a value is not null print(z!.isEven); // Asserts that 'z' is not null and prints whether 'z' is even. }

Explanation for Null safety:

  • Dart introduced null safety to prevent null reference errors. Variables can be non-nullable or nullable.

  • Non-nullable variables must be initialized before use, otherwise, it will cause a compilation error.

  • Nullable variables are denoted with a question mark ?. They can hold either a value of their type or null.

  • The ?. operator (null safety operator) allows concise null checks. It returns null if the object is null, otherwise, it accesses the property or calls the method.

  • The ! operator (null assertion operator) asserts that the operand is non-null. It's useful when the programmer knows that the value isn't null and wants to access it directly without a null check. However, if the value is null, it will cause a runtime error.

Conclusion

Understanding these fundamental data structures and null safety features is crucial for writing efficient and reliable Dart code. Incorporating them into your projects can significantly improve code readability, maintainability, and robustness.

🌟 Stay Connected! 🌟

Hey there, awesome reader! 👋 Want to stay updated with my latest insights? Follow me on social media!

🐦 📸 📘 💻 🌐

Sadanand Gadwal


Written by sadanandgadwal | Software engineer 📚.Sharing coding related stuff. #sadanandgadwal
Published by HackerNoon on 2024/04/19