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)