Today we'll be learning about extremely important collection types in Dart. In this lesson, we'll focus on List and Set - powerful tools for managing and manipulating multiple data items efficiently in your programs.
I. List: An Ordered Collection of Data
A List is the most commonly used collection type in Dart. It's an ordered and allowing duplicates collection of data, similar to arrays in other programming languages.
1. How to Create a List
There are several ways to create a List, with these being the most common:
Method 1: Using literals (Recommended)
void main() {
// Create a list of integers
List<int> numbers = [1, 2, 3, 4, 5];
// Create a list of strings
List<String> fruits = ['Apple', 'Banana', 'Orange'];
// Create a list with mixed types (not recommended, specify types when possible)
List<dynamic> mixed = [1, 'hello', true, 3.14];
print(numbers); // Output: [1, 2, 3, 4, 5]
print(fruits); // Output: [Apple, Banana, Orange]
}
Method 2: Using List constructors
void main() {
// Create an empty list
List<String> emptyList = List.empty();
// Create a fixed-length list (initialized with a value)
List<int> fixedList = List.filled(3, 0); // Length 3, initial value 0
print(fixedList); // Output: [0, 0, 0]
// Create a growable list
List<String> growableList = List<String>.empty(growable: true);
growableList.add('dart');
print(growableList); // Output: [dart]
}
2. Accessing and Modifying List Elements
List elements are accessed using indices (starting from 0):
void main() {
List<String> colors = ['Red', 'Green', 'Blue'];
// Access elements
print(colors[0]); // Output: Red
print(colors[2]); // Output: Blue
// Modify elements
colors[1] = 'Yellow';
print(colors); // Output: [Red, Yellow, Blue]
// Get list length
print(colors.length); // Output: 3
}
3. Adding and Removing Elements
For growable lists, we can dynamically add or remove elements:
void main() {
List<int> nums = [10, 20];
// Add a single element
nums.add(30);
print(nums); // Output: [10, 20, 30]
// Add multiple elements
nums.addAll([40, 50]);
print(nums); // Output: [10, 20, 30, 40, 50]
// Insert element at specific position
nums.insert(1, 15); // Insert 15 at index 1
print(nums); // Output: [10, 15, 20, 30, 40, 50]
// Remove element by value (removes first occurrence)
nums.remove(20);
print(nums); // Output: [10, 15, 30, 40, 50]
// Remove element by index
nums.removeAt(0);
print(nums); // Output: [15, 30, 40, 50]
// Clear the list
nums.clear();
print(nums); // Output: []
}
4. Iterating Over Lists
Traversing lists is a common operation, with the for-in loop being most frequently used:
void main() {
List<String> languages = ['Dart', 'Java', 'Python', 'JavaScript'];
// Method 1: for-in loop (Recommended)
for (String lang in languages) {
print(lang);
}
// Method 2: Standard for loop (when index is needed)
for (int i = 0; i < languages.length; i++) {
print('Index $i: ${languages[i]}');
}
// Method 3: forEach method (functional programming style)
languages.forEach((lang) {
print('Language: $lang');
});
}
II. Set: An Unordered Collection with Unique Elements
A Set is an unordered collection of unique elements, ideal for storing data where you don't want duplicates.
1. Creating a Set
void main() {
// Method 1: Using literals (note the curly braces)
Set<int> numbers = {1, 2, 3, 4};
// Method 2: Using Set constructor
Set<String> fruits = Set.from([
'Apple',
'Banana',
'Apple',
]); // Automatically removes duplicates
print(numbers); // Output: {1, 2, 3, 4}
print(fruits); // Output: {Apple, Banana} (duplicate "Apple" is removed)
// Creating empty Sets - compatible with all Dart versions
Set<String> emptySet1 = <String>{}; // Recommended literal syntax
Set<String> emptySet2 = Set<String>(); // Constructor syntax
print(emptySet1.isEmpty); // Output: true
print(emptySet2.isEmpty); // Output: true
}
Note: {} creates a Set by default, not a Map (which we'll learn about later). If you want to create an empty Map, specify the type with Map().
2. Core Feature of Set: Automatic Duplicate Removal
When adding duplicate elements, Set automatically ignores them:
void main() {
Set<String> names = {'Zhang San', 'Li Si', 'Zhang San'};
print(names); // Output: {Zhang San, Li Si}
// Adding a duplicate element
names.add('Li Si');
print(names); // Output: {Zhang San, Li Si} (no change)
}
This feature is very useful for deduplication tasks:
void main() {
// Original list with duplicates
List<int> rawData = [1, 2, 2, 3, 3, 3, 4];
// Convert to Set for deduplication, then back to List
List<int> uniqueData = rawData.toSet().toList();
print(uniqueData); // Output: [1, 2, 3, 4]
}
3. Set Operations: Intersection, Union, and Difference
Set provides convenient methods for set operations:
- Union: All elements from both sets (without duplicates)
- Intersection: Elements common to both sets
- Difference: Elements in the current set that are not in the other set
void main() {
Set<int> a = {1, 2, 3, 4};
Set<int> b = {3, 4, 5, 6};
// Union: all elements from a and b
Set<int> union = a.union(b);
print(union); // Output: {1, 2, 3, 4, 5, 6}
// Intersection: elements common to both a and b
Set<int> intersection = a.intersection(b);
print(intersection); // Output: {3, 4}
// Difference: elements in a that are not in b
Set<int> difference = a.difference(b);
print(difference); // Output: {1, 2}
}
4. Adding and Removing Elements in Set
Set operations are similar to List, but since it's unordered, there are no index-related methods:
void main() {
Set<String> countries = {'China', 'USA'};
// Add an element
countries.add('Japan');
print(countries); // Output: {China, USA, Japan} (order may vary)
// Add multiple elements
countries.addAll(['France', 'Germany']);
print(countries); // Output: {China, USA, Japan, France, Germany}
// Remove an element
countries.remove('USA');
print(countries); // Output: {China, Japan, France, Germany}
// Clear the set
countries.clear();
print(countries); // Output: {}
}
III. Common Collection Methods (map/where/toList etc.)
Dart collections provide many powerful methods that allow us to process data more concisely. These methods work with both Lists and Sets.
1. map(): Transform Elements
The map() method transforms each element in a collection according to specified rules and returns a new iterable:
void main() {
List<int> numbers = [1, 2, 3, 4];
// Multiply each number by 2
var doubled = numbers.map((n) => n * 2);
// map() returns an Iterable, often converted to List
List<int> doubledList = doubled.toList();
print(doubledList); // Output: [2, 4, 6, 8]
// String processing example
List<String> names = ['Zhang San', 'Li Si', 'Wang Wu'];
List<String> greetings = names.map((name) => 'Hello, $name!').toList();
print(
greetings,
); // Output: [Hello, Zhang San!, Hello, Li Si!, Hello, Wang Wu!]
}
2. where(): Filter Elements
The where() method filters elements based on a condition and returns an iterable containing elements that meet the condition:
void main() {
List<int> ages = [12, 18, 20, 15, 25, 30];
// Filter adults (age >= 18)
var adults = ages.where((age) => age >= 18);
List<int> adultList = adults.toList();
print(adultList); // Output: [18, 20, 25, 30]
// Set filtering example
Set<double> prices = {19.9, 29.9, 9.9, 39.9, 5.9};
List<double> cheapPrices = prices.where((p) => p < 20).toList();
print(cheapPrices); // Output: [19.9, 9.9, 5.9]
}
3. toList() and toSet(): Type Conversion
These methods convert between List and Set:
void main() {
Set<String> set = {'a', 'b', 'c'};
List<String> list = set.toList(); // Set to List
print(list); // Output: [a, b, c] (order may vary)
List<String> duplicateList = ['a', 'a', 'b'];
Set<String> uniqueSet = duplicateList
.toSet(); // List to Set (removes duplicates)
print(uniqueSet); // Output: {a, b}
}
4. contains(): Check if an Element Exists
void main() {
List<String> fruits = ['Apple', 'Banana', 'Orange'];
print(fruits.contains('Banana')); // Output: true
print(fruits.contains('Watermelon')); // Output: false
Set<int> nums = {1, 3, 5};
print(nums.contains(3)); // Output: true
}
5. any() and every(): Evaluate Conditions
- any(): Returns true if at least one element satisfies the condition
- every(): Returns true only if all elements satisfy the condition
void main() {
List<int> scores = [85, 92, 78, 60];
// Are there any failing scores (<60)?
bool hasFailed = scores.any((s) => s < 60);
print(hasFailed); // Output: false (all are >=60)
// Did all scores pass?
bool allPassed = scores.every((s) => s >= 60);
print(allPassed); // Output: true
}
IV. Differences Between List and Set, and When to Use Each
Feature | List | Set |
---|---|---|
Order | Ordered (preserves insertion order) | Unordered (partially ordered in Dart 3.0+) |
Duplicates | Allows duplicate elements | No duplicate elements |
Index access | Supported (via index) | Not supported (no index) |
Lookup speed | Decreases with more elements | Consistently high (hash table implementation) |
Recommendation:
- Use List when you need to maintain element order or allow duplicates
- Use Set when you need to avoid duplicates or efficiently check for element existence
- Use Set when you need to perform frequent set operations (intersection, union, etc.)
Top comments (0)