Lists
Fixed-length and Growable Lists
Common List Methods (add, remove, sort, etc.)
Sets
Packages
Queues
Maps
Key-Value Pairs
Iterating over Maps
Iterables and Generators
sync* and async*
Collections in Dart include lists, sets, and maps, which allow developers to store multiple values in a single variable and manipulate them efficiently. Each collection type has its unique characteristics and use cases.
A List in Dart is an ordered collection of items, where each item can be accessed by an index. Lists can contain duplicate elements and can be either fixed-length or growable.
Example:
void main() {
// Fixed-length list
List<int> fixedList = List.filled(3, 0); // Creates a list with 3 items, each initialized to 0
fixedList[0] = 10;
fixedList[1] = 20;
fixedList[2] = 30;
print("Fixed List: $fixedList");
// Growable list
List<String> growableList = ["apple", "banana"];
growableList.add("cherry");
print("Growable List: $growableList");
// Iterating over a list
for (var item in growableList) {
print(item);
}
}
A Set is an unordered collection of unique items. It does not allow duplicate elements. Sets are useful when you want to ensure all elements are unique or when the order of items doesn’t matter.
Example:
void main() {
Set<String> fruits = {"apple", "banana", "apple"}; // "apple" is duplicated but will appear only once
fruits.add("cherry");
print("Set: $fruits"); // Output: {apple, banana, cherry}
// Checking if an element exists
print("Contains 'apple': ${fruits.contains('apple')}");
// Iterating over a set
for (var fruit in fruits) {
print(fruit);
}
}
A Map is an unordered collection of key-value pairs. Each key is unique, but values can be duplicated. Maps are similar to dictionaries or hash tables in other languages, where each key maps to a specific value.
Example:
void main() {
// Creating a map
Map<String, int> phoneNumbers = {
"Alice": 1234567890,
"Bob": 9876543210
};
phoneNumbers["Charlie"] = 1122334455; // Adding a new key-value pair
print("Map: $phoneNumbers");
// Accessing values by key
print("Alice's phone number: ${phoneNumbers["Alice"]}");
// Iterating over a map
phoneNumbers.forEach((key, value) {
print("$key: $value");
});
}
Dart collections can also be classified by type. Here are the main types:
Synchronous collections are used when we want to perform operations in a sequential or synchronous manner.
Example of Synchronous List:
void main() {
List<int> numbers = [1, 2, 3, 4];
numbers.add(5); // Adding an element synchronously
print("Synchronous List: $numbers");
}
Asynchronous collections are used when handling asynchronous data, often with Dart streams or futures.
Example with Stream:
import 'dart:async';
void main() async {
Stream<int> numberStream = Stream.fromIterable([1, 2, 3, 4, 5]);
await for (var number in numberStream) {
print("Stream number: $number");
}
}
An Iterable is an interface implemented by collections that can be iterated over (such as List and Set). Iterable collections allow us to use for-in loops and methods like map, where, and reduce.
Example of Iterable:
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
Iterable<int> evenNumbers = numbers.where((number) => number.isEven);
print("Even numbers: $evenNumbers");
}
Dart collections come with several built-in methods that allow for manipulation and querying, including:
Adding elements (add, addAll)
Removing elements (remove, removeWhere)
Checking elements (contains, isEmpty)
Transforming elements (map, reduce, forEach)
Example of Collection Operations:
void main() {
List<int> numbers = [1, 2, 3, 4, 5];
// Using add and remove methods
numbers.add(6);
numbers.remove(3);
print("List after add and remove: $numbers");
// Using map to transform each element
List<int> doubled = numbers.map((number) => number * 2).toList();
print("Doubled values: $doubled");
// Using reduce to get the sum of all elements
int sum = numbers.reduce((a, b) => a + b);
print("Sum of numbers: $sum");
}
Here are ten Dart programs that demonstrate the use of various libraries in the dart:collection package, including List, Set, Map, Queue, LinkedList, HashMap, and more. These programs illustrate how Dart collections can be used in practical scenarios.
void main() {
List<String> fruits = ["apple", "banana", "cherry", "apple"];
// Remove duplicates
fruits = fruits.toSet().toList();
print("Unique Fruits: $fruits");
// Sort the list
fruits.sort();
print("Sorted Fruits: $fruits");
}
import 'dart:collection';
void main() {
HashMap<String, int> ages = HashMap();
ages["Alice"] = 30;
ages["Bob"] = 25;
ages["Charlie"] = 35;
ages.forEach((name, age) => print("$name is $age years old"));
}
import 'dart:collection';
void main() {
Queue<String> tasks = Queue();
tasks.addAll(["Clean", "Cook", "Exercise"]);
while (tasks.isNotEmpty) {
print("Performing task: ${tasks.removeFirst()}");
}
}
import 'dart:collection';
void main() {
LinkedHashSet<int> numbers = LinkedHashSet();
numbers.addAll([3, 1, 2, 3, 4, 1]);
print("Ordered Unique Numbers: $numbers");
}
import 'dart:collection';
class Node extends LinkedListEntry<Node> {
String name;
Node(this.name);
}
void main() {
LinkedList<Node> people = LinkedList<Node>();
people.addAll([Node("Alice"), Node("Bob"), Node("Charlie")]);
for (var person in people) {
print("Person: ${person.name}");
}
}
import 'dart:collection';
import 'dart:math';
void main() {
HashSet<int> uniqueNumbers = HashSet();
Random random = Random();
while (uniqueNumbers.length < 5) {
uniqueNumbers.add(random.nextInt(10));
}
print("Unique Random Numbers: $uniqueNumbers");
}
import 'dart:collection';
void main() {
SplayTreeMap<String, int> students = SplayTreeMap();
students["Alice"] = 90;
students["Bob"] = 85;
students["Charlie"] = 95;
students.forEach((name, score) => print("$name scored $score"));
}
void main() {
Map<String, int> wordCount = {};
List<String> words = ["apple", "banana", "apple", "cherry", "banana"];
for (var word in words) {
wordCount.update(word, (count) => count + 1, ifAbsent: () => 1);
}
print("Word Count: $wordCount");
}
import 'dart:collection';
void main() {
Queue<int> stack = Queue<int>();
// Push elements to stack
stack.addFirst(10);
stack.addFirst(20);
stack.addFirst(30);
// Pop elements from stack
while (stack.isNotEmpty) {
print("Popped: ${stack.removeFirst()}");
}
}
void main() {
List<Map<String, dynamic>> tasks = [
{"task": "Clean", "priority": 3},
{"task": "Study", "priority": 1},
{"task": "Exercise", "priority": 2},
];
// Sort tasks based on priority
tasks.sort((a, b) => a["priority"].compareTo(b["priority"]));
tasks.forEach((task) {
print("Task: ${task['task']}, Priority: ${task['priority']}");
});
}
In Dart, generics provide a way to create reusable, type-safe collections and classes. By using generics, you can specify types as parameters, enabling collections to be type-specific and reducing the need for type casting. This ensures type safety at compile-time, making your code more robust and easier to maintain.
For example, consider the following List without generics:
dart
Copy code
List items = []; // A list without generics
items.add(10);
items.add("Hello"); // This is allowed, but can lead to runtime errors
Without generics, List can hold any type, which may lead to runtime errors if you mistakenly try to access the list items with incorrect type assumptions.
Using generics in collections, you can enforce a specific type, making the collection type-safe. Here’s how you can use a List<int> to only accept integers:
dart
Copy code
List<int> numbers = []; // A list with generics
numbers.add(10); // Allowed
// numbers.add("Hello"); // Error: 'String' can't be assigned to parameter type 'int'
In this example, List<int> specifies that this list can only contain int values. If you try to add a different type (like a String), Dart throws an error at compile-time, preventing potential runtime issues.
Dart’s core library includes generic collection types:
List: List<T> specifies a list of elements of type T.
Set: Set<T> specifies a set of elements of type T.
Map: Map<K, V> specifies a map with keys of type K and values of type V.
Here’s an example with Map:
dart
Copy code
Map<String, int> ages = {
'Alice': 25,
'Bob': 30
};
// This map will only allow String keys and int values
By using generics, Dart enables collections to be more reliable, type-safe, and clear in their intent. This also allows the compiler to optimize and enforce type safety, resulting in more maintainable code.
4o
In Dart, collections are organized into libraries that provide essential data structures and utilities for managing groups of data. The main library for collections in Dart is the dart:collection library, which complements the core dart:core library by providing additional types and functionality.
Here’s an overview of the primary libraries related to collections in Dart:
The dart:core library is automatically imported into every Dart program and provides essential classes for collections:
List: An ordered collection of elements, accessible by index.
Set: An unordered collection of unique elements.
Map: A collection of key-value pairs, where keys are unique.
These collection types are generic, allowing for strong typing (e.g., List<int>, Set<String>, Map<String, int>).
Example:
dart
Copy code
List<int> numbers = [1, 2, 3];
Set<String> fruits = {'apple', 'banana', 'orange'};
Map<String, int> scores = {'Alice': 90, 'Bob': 85};
The dart:collection library expands the core collection capabilities with more specialized collection types and utilities. It includes:
Queue: A double-ended queue that supports adding and removing elements from both ends.
LinkedList: A doubly linked list, useful when frequent insertions and deletions are required.
SplayTreeSet and SplayTreeMap: Sorted collections using a self-balancing binary tree.
HashSet and HashMap: Hash-based collections that are optimized for performance with no guarantees on element order.
You need to import dart:collection to use these specialized types.
Example:
dart
Copy code
import 'dart:collection';
Queue<int> queue = Queue<int>();
queue.addAll([1, 2, 3]);
SplayTreeSet<String> sortedSet = SplayTreeSet<String>();
sortedSet.addAll(['banana', 'apple', 'orange']);
The dart:collection library also provides base classes for creating custom collection types. These base classes, such as ListBase, SetBase, and MapBase, allow you to extend or modify the behavior of Dart’s collection classes by implementing the methods and properties specific to your use case.
Example of Custom Collection:
dart
Copy code
import 'dart:collection';
class CustomList<E> extends ListBase<E> {
final List<E> _innerList = [];
@override
int get length => _innerList.length;
@override
set length(int newLength) {
_innerList.length = newLength;
}
@override
E operator [](int index) => _innerList[index];
@override
void operator []=(int index, E value) {
_innerList[index] = value;
}
}
dart:core: Basic collections like List, Set, and Map.
dart:collection: Specialized collections (e.g., Queue, LinkedList) and classes for creating custom collections.
In Dart, a List is an ordered collection that allows you to store a sequence of elements. It is similar to an array in other programming languages and is part of Dart’s core library, dart:core, so you can use it without any imports. Lists in Dart are zero-indexed, meaning that the first element is at index 0.
Ordered: Elements in a list are stored in a specific order, and they maintain this order.
Indexed: Each element has an index, starting from 0 for the first element.
Generic: You can specify the type of elements a list can contain using generics, such as List<int> for integers or List<String> for strings.
Mutable or Immutable: Lists can be either mutable (changeable) or immutable (unchangeable).
Fixed-Length List: A list with a fixed size that cannot grow or shrink.
Growable List: A list that can dynamically increase or decrease in size.
1. Fixed-Length List
A fixed-length list is created with a predefined length, and you cannot add or remove items after creation.
dart
Copy code
List<int> fixedList = List<int>.filled(5, 0); // Creates a fixed-length list of integers with 5 elements initialized to 0
fixedList[0] = 10; // You can change values
2. Growable List
A growable list can dynamically change in size. You can add, remove, or modify elements.
dart
Copy code
List<String> growableList = []; // Empty growable list
growableList.add("apple");
growableList.add("banana");
growableList.add("orange");
Alternatively, you can use the list literal syntax:
dart
Copy code
List<String> fruits = ["apple", "banana", "orange"];
Accessing Elements
Elements in a list can be accessed using their index:
dart
Copy code
print(fruits[0]); // Outputs: apple
Modifying Elements
You can modify elements at specific indices:
dart
Copy code
fruits[1] = "blueberry"; // Replaces "banana" with "blueberry"
Adding and Removing Elements (Growable List)
For growable lists, you can use:
add(element): Adds a single element at the end of the list.
addAll([element1, element2, ...]): Adds multiple elements at the end.
insert(index, element): Inserts an element at a specific index.
remove(element): Removes the first occurrence of an element.
removeAt(index): Removes the element at a specific index.
dart
Copy code
fruits.add("grape");
fruits.remove("apple");
length: Returns the number of elements in the list.
isEmpty and isNotEmpty: Checks if the list is empty or not.
contains(element): Checks if the list contains a specific element.
indexOf(element): Returns the index of the first occurrence of an element.
dart
Copy code
print(fruits.length); // Outputs: 3
print(fruits.contains("orange")); // Outputs: true
You can loop through a list in several ways:
For Loop:
dart
Copy code
for (int i = 0; i < fruits.length; i++) {
print(fruits[i]);
}
For-in Loop:
dart
Copy code
for (var fruit in fruits) {
print(fruit);
}
ForEach Method:
dart
Copy code
fruits.forEach((fruit) => print(fruit));
dart
Copy code
void main() {
List<String> names = ["Alice", "Bob", "Charlie"];
names.add("Diana"); // Add a new name
names.remove("Alice"); // Remove a name
print(names.length); // Output: 3
print(names.contains("Bob")); // Output: true
for (var name in names) {
print(name); // Prints each name in the list
}
}
Lists are ordered collections that allow indexing and are commonly used for storing sequences of items.
Generics let you specify the type of elements in a list, ensuring type safety.
Lists can be fixed-length or growable, making them flexible for various use cases.
Dart provides various methods and properties for manipulating lists, making them a powerful and essential data structure.
In Dart, a Map is a collection of key-value pairs, where each key is unique, and each key maps to a single value. It is similar to dictionaries in Python or hash maps in other languages and is part of Dart’s core library, dart:core, so you don’t need to import anything extra to use it.
Key-Value Pair Structure: Each item in a Map consists of a key and its associated value.
Unique Keys: Each key must be unique, but values can be duplicated.
Unordered: In most cases, the elements in a Map do not follow a specific order. However, LinkedHashMap retains the order of insertion.
Dart’s core library provides different types of maps:
HashMap: The default type of map, optimized for fast lookup but does not guarantee order.
LinkedHashMap: Maintains the order of key-value pairs based on insertion order.
SplayTreeMap: A sorted map that automatically keeps keys sorted based on their natural ordering or a provided comparator.
There are a few ways to create a map in Dart:
1. Using Map Literals
You can create a map using the literal syntax:
dart
Copy code
Map<String, int> ages = {
'Alice': 25,
'Bob': 30,
'Charlie': 35,
};
2. Using Map Constructor
You can also create an empty map and add entries to it later:
dart
Copy code
Map<String, String> countries = Map();
countries['US'] = 'United States';
countries['CA'] = 'Canada';
Accessing Elements
You can access values by providing the corresponding key:
dart
Copy code
print(ages['Alice']); // Outputs: 25
If the key is not present, it returns null by default.
Adding and Updating Elements
You can add or update elements in a map by assigning values to keys:
dart
Copy code
ages['David'] = 40; // Adds a new key-value pair
ages['Alice'] = 26; // Updates the value for the key 'Alice'
Removing Elements
To remove an element by its key, use the remove() method:
dart
Copy code
ages.remove('Bob'); // Removes the entry for 'Bob'
You can also use clear() to remove all entries:
dart
Copy code
ages.clear(); // Empties the map
Some helpful properties and methods of maps:
length: Returns the number of key-value pairs in the map.
isEmpty and isNotEmpty: Checks if the map is empty or not.
containsKey(key): Checks if the map contains a specific key.
containsValue(value): Checks if the map contains a specific value.
keys: Returns an iterable of all keys in the map.
values: Returns an iterable of all values in the map.
dart
Copy code
print(ages.length); // Outputs: 3
print(ages.containsKey('Alice')); // Outputs: true
print(ages.keys); // Outputs: (Alice, David, Charlie)
print(ages.values); // Outputs: (26, 40, 35)
You can iterate over a map in various ways:
Using ForEach:
dart
Copy code
ages.forEach((key, value) {
print('$key is $value years old');
});
Using For-In Loop:
dart
Copy code
for (var entry in ages.entries) {
print('${entry.key} is ${entry.value} years old');
}
Using Keys and Values Separately:
dart
Copy code
for (var key in ages.keys) {
print('$key: ${ages[key]}');
}
Here is a practical example that shows how to use a map:
dart
Copy code
void main() {
Map<String, double> productPrices = {
'Apple': 1.99,
'Banana': 0.99,
'Orange': 1.29,
};
// Accessing a value
print('The price of an Apple is ${productPrices['Apple']}');
// Adding a new product
productPrices['Grapes'] = 2.49;
// Updating a price
productPrices['Banana'] = 1.09;
// Removing a product
productPrices.remove('Orange');
// Checking if a key exists
if (productPrices.containsKey('Apple')) {
print('Apple is available');
}
// Iterating over map entries
productPrices.forEach((product, price) {
print('$product: \$$price');
});
}
Maps in Dart are collections of key-value pairs, where keys are unique.
Types of Maps: HashMap, LinkedHashMap, SplayTreeMap.
Properties and methods like length, isEmpty, containsKey(), and remove().
Useful for scenarios where you need to associate keys with values, like storing product prices, user information, or settings.
In Dart, a package is a collection of code organized in a way that can be shared and reused across different projects. Packages can include libraries, assets, tools, and other resources, making it easy to add and manage new functionality within a project. Packages are particularly useful for organizing Dart code and for managing dependencies in larger applications, as they allow you to share and reuse code easily.
The Dart ecosystem has a rich collection of packages available on the Dart Pub repository, which is Dart's package manager. These packages help with everything from UI design to state management, database access, network requests, and more.
A typical Dart package has the following structure:
bash
Copy code
my_package/
├── lib/
│ ├── my_package.dart # Main library file
│ ├── src/ # Directory for private files
│ └── ... # Other Dart files
├── example/ # Directory for example applications
├── test/ # Directory for tests
├── pubspec.yaml # Package configuration file
└── README.md # Documentation for the package
lib/: Contains the main code of the package, including public libraries that other code can import.
The primary library file (e.g., my_package.dart) acts as the entry point for the package and often exports other libraries for convenience.
src/: Holds internal libraries that are private to the package, not intended for direct use outside the package.
example/: Contains example code demonstrating how to use the package.
test/: Contains unit tests for the package’s code.
pubspec.yaml: The configuration file for a Dart package. It specifies the package's dependencies, version, name, author, and other metadata.
1. Adding a Package Dependency
To use a package in your Dart project, add it to your pubspec.yaml file under dependencies. For example, if you want to add the http package for making HTTP requests:
yaml
Copy code
dependencies:
http: ^0.13.4
After adding the dependency, run the following command to install the package:
bash
Copy code
dart pub get
2. Importing a Package
Once you’ve added a package dependency and installed it, you can import it into your Dart code:
dart
Copy code
import 'package:http/http.dart' as http;
void main() async {
var response = await http.get(Uri.parse('https://jsonplaceholder.typicode.com/posts'));
print(response.body);
}
Dart supports different types of packages:
Dart Packages: Pure Dart code packages, which can be used in both Dart console applications and Flutter projects. They usually contain libraries without platform-specific code.
Flutter Packages: Packages specifically designed for Flutter applications. These may include Flutter widgets, plugins, and assets for building UI elements.
Plugin Packages: Flutter packages that contain platform-specific code for integrating with native APIs on iOS, Android, or other platforms. Plugins allow Flutter apps to access device-specific functionalities like the camera, GPS, or Bluetooth.
To create a package, you can use the following command:
bash
Copy code
dart create -t package_simple my_package
Or for a Flutter package:
bash
Copy code
flutter create --template=package my_flutter_package
This command will generate the basic package structure for you, including the lib/ directory and pubspec.yaml file.
To publish your package to pub.dev, follow these steps:
Ensure you have a valid pubspec.yaml with metadata like name, description, and version.
Test the package to ensure it works as expected.
Run dart pub publish and follow the prompts to publish it to the Dart package repository.
Once published, anyone can add your package to their projects.
Here’s an example package structure for a package that provides utilities for list and map manipulation:
plaintext
Copy code
list_map_utils/
├── lib/
│ ├── list_map_utils.dart # Main entry file
│ └── src/
│ ├── list_utils.dart # Utility functions for lists
│ └── map_utils.dart # Utility functions for maps
├── test/
│ ├── list_utils_test.dart # Tests for list utilities
│ └── map_utils_test.dart # Tests for map utilities
├── example/
│ └── example.dart # Example usage
├── pubspec.yaml # Package metadata and dependencies
└── README.md # Documentation
Packages in Dart are a way to organize and share code, often hosted on Dart's Pub repository.
Package types include Dart packages, Flutter packages, and plugins.
pubspec.yaml is the configuration file for defining package dependencies and metadata.
Adding packages in Dart involves listing them in pubspec.yaml and importing them in your code.
Dart packages are reusable and make development faster by providing ready-to-use functionality and modular code.
In Dart, a Set is an unordered collection of unique elements, meaning it does not allow duplicate values. Sets are useful when you need to store unique items and don't care about the order. Like List and Map, Set is part of Dart’s core library (dart:core), so you don’t need to import any additional libraries to use it.
Unique Elements: Each item in a set must be unique. If you try to add a duplicate element, it will be ignored.
Unordered: Elements in a set do not have a fixed order, and you cannot access elements by index.
Efficient Membership Testing: Sets are optimized for checking if an element is present, which is faster than lists.
Dart’s core library provides several types of sets:
HashSet: The default set type, optimized for performance, with no guarantee of element order.
LinkedHashSet: Maintains the order of elements based on their insertion order.
SplayTreeSet: A sorted set that automatically sorts elements based on their natural ordering or a provided comparator.
There are several ways to create a set in Dart:
1. Using Set Literals
You can create a set using curly braces {}:
dart
Copy code
Set<String> fruits = {'apple', 'banana', 'orange'};
2. Using Set Constructor
You can create an empty set and then add elements to it:
dart
Copy code
Set<int> numbers = Set(); // Creates an empty set
numbers.add(1);
numbers.add(2);
To specify the type of a set, you can use generics like Set<int>, Set<String>, etc.
You can add elements to a set using:
add(element): Adds a single element to the set.
addAll([element1, element2, ...]): Adds multiple elements at once.
dart
Copy code
fruits.add('grape'); // Adds 'grape' to the set
fruits.addAll(['lemon', 'lime']); // Adds multiple elements
If an element already exists in the set, it won’t be added again.
You can remove elements from a set using:
remove(element): Removes a specific element if it exists.
removeAll(elements): Removes all elements present in a given iterable.
clear(): Removes all elements from the set.
dart
Copy code
fruits.remove('banana'); // Removes 'banana' from the set
fruits.clear(); // Empties the set
Since sets are unordered and do not have indices, you cannot access elements by an index. Instead, you can:
Use a for-in loop or forEach to iterate through the set.
Use methods like contains(element) to check if an element exists in the set.
dart
Copy code
if (fruits.contains('apple')) {
print('Apple is in the set');
}
Sets in Dart support common mathematical set operations, such as:
Union: Combines elements from two sets, keeping only unique elements.
dart
Copy code
var set1 = {1, 2, 3};
var set2 = {3, 4, 5};
var unionSet = set1.union(set2); // {1, 2, 3, 4, 5}
Intersection: Returns only the elements that are present in both sets.
dart
Copy code
var intersectionSet = set1.intersection(set2); // {3}
Difference: Returns elements that are in the first set but not in the second set.
dart
Copy code
var differenceSet = set1.difference(set2); // {1, 2}
Some useful properties and methods for sets:
length: Returns the number of elements in the set.
isEmpty and isNotEmpty: Checks if the set is empty or not.
contains(element): Checks if a specific element is present in the set.
lookup(element): Finds an element in the set that is equal to the given element.
Here is a simple example demonstrating set operations:
dart
Copy code
void main() {
Set<String> countries = {'USA', 'Canada', 'Mexico'};
countries.add('UK'); // Add an element
countries.remove('Mexico'); // Remove an element
print(countries.contains('Canada')); // Output: true
print(countries.length); // Output: 3
// Set operations
Set<String> europeanCountries = {'France', 'Germany', 'UK'};
var allCountries = countries.union(europeanCountries);
print(allCountries); // {USA, Canada, UK, France, Germany}
var commonCountries = countries.intersection(europeanCountries);
print(commonCountries); // {UK}
}
Sets in Dart are collections of unique, unordered elements.
Types of Sets: HashSet, LinkedHashSet, and SplayTreeSet.
Set operations: Union, Intersection, and Difference.
Useful when you need a collection of unique items and efficient membership testing without worrying about order.
In Dart, a Queue is a collection that allows items to be added or removed in a specific order. A queue is part of Dart's dart:collection library, and it is generally used to store data that needs to follow a First-In-First-Out (FIFO) or Last-In-First-Out (LIFO) order, depending on how elements are added and removed.
Queues are particularly useful in scenarios where elements need to be processed in the same order they were added, such as task scheduling or handling sequential events.
FIFO (First-In-First-Out): In a traditional queue structure, elements are added to the end of the queue and removed from the front.
LIFO (Last-In-First-Out): A queue can also act as a stack if elements are added and removed from the same end.
Efficient Insertion and Deletion: Queues allow efficient insertion and deletion at both the front and the end.
To use a Queue in Dart, you need to import it from the dart:collection library:
dart
Copy code
import 'dart:collection';
You can create an empty queue and add elements to it. Dart's Queue is generic, so you can specify the type of elements it will contain:
dart
Copy code
import 'dart:collection';
void main() {
Queue<int> numbers = Queue<int>();
numbers.addAll([1, 2, 3, 4, 5]);
print(numbers); // Output: {1, 2, 3, 4, 5}
}
There are two primary ways to add elements to a queue:
addFirst(element): Adds an element to the front of the queue.
addLast(element): Adds an element to the end of the queue.
dart
Copy code
numbers.addFirst(0); // Adds 0 at the front
numbers.addLast(6); // Adds 6 at the end
print(numbers); // Output: {0, 1, 2, 3, 4, 5, 6}
Similarly, there are two main ways to remove elements:
removeFirst(): Removes the element at the front of the queue.
removeLast(): Removes the element at the end of the queue.
dart
Copy code
numbers.removeFirst(); // Removes the first element (0)
numbers.removeLast(); // Removes the last element (6)
print(numbers); // Output: {1, 2, 3, 4, 5}
Some helpful properties and methods for working with queues:
length: Returns the number of elements in the queue.
isEmpty and isNotEmpty: Checks if the queue is empty or not.
first: Accesses the first element without removing it.
last: Accesses the last element without removing it.
dart
Copy code
print(numbers.length); // Output: 5
print(numbers.isEmpty); // Output: false
print(numbers.first); // Output: 1
print(numbers.last); // Output: 5
Here is an example that demonstrates adding and removing elements from a queue:
dart
Copy code
import 'dart:collection';
void main() {
Queue<String> tasks = Queue<String>();
// Adding tasks to the queue
tasks.addLast("Task 1");
tasks.addLast("Task 2");
tasks.addLast("Task 3");
print("Initial queue: $tasks"); // Output: {Task 1, Task 2, Task 3}
// Processing tasks in FIFO order
while (tasks.isNotEmpty) {
print("Processing ${tasks.removeFirst()}");
}
print("Queue after processing: $tasks"); // Output: {}
}
Queue in Dart is an ordered collection where you can add or remove items from both ends.
FIFO: By adding at the end and removing from the front, you achieve a FIFO order.
LIFO: By adding and removing from the same end, a queue can behave like a stack.
Useful methods: addFirst(), addLast(), removeFirst(), removeLast(), first, last, and length.
Queues are ideal for task scheduling, processing requests, or managing any data where insertion and deletion order is essential.