Lesson 14 min

Set — Unique Values & Operations

00:00 / 00:00

Set — Unique Values & Operations

A Set in Dart is a collection of unique values — no duplicates allowed. Unlike a List, a Set does not preserve insertion order (by default) and has no concept of index-based access. These properties make Sets extremely useful in specific scenarios.


1. What is a Set?

Think of a Set like a bag of unique items:

  • You can add items to the bag
  • The bag automatically ignores items you already have
  • You cannot ask for the "3rd item" — there is no index
  • Checking if an item exists is very fast (O(1) — constant time)
dart
void main() { Set<int> numbers = {1, 2, 3, 4, 5}; print(numbers); // {1, 2, 3, 4, 5} // Duplicates are automatically removed Set<String> fruits = {'apple', 'mango', 'apple', 'banana', 'mango'}; print(fruits); // {apple, mango, banana} print(fruits.length); // 3 — only unique values }

2. Creating Sets

Literal {} Syntax

dart
void main() { // Typed Set Set<int> primes = {2, 3, 5, 7, 11}; Set<String> colors = {'red', 'green', 'blue'}; // Type inferred var days = {'Mon', 'Tue', 'Wed', 'Thu', 'Fri'}; // Set<String> // Empty Set — IMPORTANT: {} alone creates a Map, not a Set! Set<int> emptySet = {}; // Correct var alsoEmpty = <int>{}; // Also correct // var wrong = {}; // This creates Map<dynamic, dynamic>! print(emptySet.runtimeType); // _Set<int> }

Set() Constructor

dart
void main() { var set1 = Set<int>(); set1.add(1); set1.add(2); print(set1); // {1, 2} }

LinkedHashSet — Ordered Set

By default, Set in Dart is a LinkedHashSet which does preserve insertion order:

dart
import 'dart:collection'; void main() { // LinkedHashSet preserves insertion order var ordered = LinkedHashSet<String>(); ordered.add('banana'); ordered.add('apple'); ordered.add('cherry'); print(ordered); // {banana, apple, cherry} // Regular Set literal also preserves order in practice (LinkedHashSet) var tags = {'flutter', 'dart', 'mobile', 'crossplatform'}; print(tags); // {flutter, dart, mobile, crossplatform} }

3. Adding Elements

dart
void main() { Set<String> languages = {'Dart', 'Python'}; // add() — single element languages.add('JavaScript'); languages.add('Dart'); // Duplicate — silently ignored print(languages); // {Dart, Python, JavaScript} print(languages.length); // 3 // addAll() — multiple elements from an Iterable languages.addAll(['Kotlin', 'Swift', 'Python']); // Python is duplicate print(languages); // {Dart, Python, JavaScript, Kotlin, Swift} }

4. Removing Elements

dart
void main() { Set<int> numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; // remove() — removes specific value (true if removed, false if not found) bool removed = numbers.remove(5); print(removed); // true print(numbers); // {1, 2, 3, 4, 6, 7, 8, 9, 10} // Remove non-existent element — no error bool notFound = numbers.remove(99); print(notFound); // false // removeWhere() — remove all matching a condition numbers.removeWhere((n) => n % 2 == 0); // remove all even print(numbers); // {1, 3, 7, 9} // clear() — remove all numbers.clear(); print(numbers); // {} }

5. Checking Membership — contains()

This is where Set really shines. Checking if a value exists is O(1) — instant, regardless of the Set's size.

dart
void main() { Set<String> visitedPages = {'/home', '/about', '/products', '/contact'}; print(visitedPages.contains('/about')); // true print(visitedPages.contains('/login')); // false // contains() also works on any Iterable, but Set is fastest List<String> pageList = ['/home', '/about', '/products', '/contact']; print(pageList.contains('/about')); // true (but O(n) — slower for large lists) }

6. Set Operations — Union, Intersection, Difference

This is the unique superpower of Sets — mathematical set operations:

union() — All elements from both sets

dart
void main() { Set<String> set1 = {'apple', 'mango', 'banana'}; Set<String> set2 = {'banana', 'grape', 'orange'}; Set<String> unionSet = set1.union(set2); print(unionSet); // {apple, mango, banana, grape, orange} // All unique elements from both sets }

intersection() — Only common elements

dart
void main() { Set<int> evens = {2, 4, 6, 8, 10}; Set<int> multOf3 = {3, 6, 9, 12}; Set<int> common = evens.intersection(multOf3); print(common); // {6} // Only elements present in BOTH sets }

difference() — Elements in first set but not in second

dart
void main() { Set<String> allStudents = {'Amit', 'Priya', 'Rahul', 'Zara', 'Dev'}; Set<String> presentToday = {'Priya', 'Rahul', 'Dev'}; Set<String> absentStudents = allStudents.difference(presentToday); print(absentStudents); // {Amit, Zara} // Elements in allStudents but NOT in presentToday }

7. Converting Between List and Set

dart
void main() { // List to Set — removes duplicates List<int> listWithDuplicates = [1, 2, 2, 3, 3, 3, 4, 5, 5]; Set<int> uniqueSet = listWithDuplicates.toSet(); print(uniqueSet); // {1, 2, 3, 4, 5} // Set back to List List<int> uniqueList = uniqueSet.toList(); print(uniqueList); // [1, 2, 3, 4, 5] // One-liner deduplication trick List<String> tags = ['dart', 'flutter', 'dart', 'mobile', 'flutter']; List<String> uniqueTags = tags.toSet().toList(); print(uniqueTags); // [dart, flutter, mobile] }

8. When to Use Set vs List

FeatureListSet
Preserves order✅ Yes✅ Yes (LinkedHashSet)
Allows duplicates✅ Yes❌ No
Index access [i]✅ Yes❌ No
contains() speed⚠️ O(n) — linear✅ O(1) — instant
Best forOrdered sequences, ordered dataUnique collections, fast lookups

Use Set when:

  • You need to ensure all values are unique
  • You frequently check membership (contains())
  • You need set operations (union, intersection, difference)

Use List when:

  • Order and position matter
  • You need index-based access
  • Duplicates are allowed or expected

9. Real Examples

Unique Tags System

dart
void main() { Set<String> articleTags = {}; void addTag(String tag) { bool added = articleTags.add(tag.toLowerCase().trim()); if (added) { print('Tag "$tag" added.'); } else { print('Tag "$tag" already exists.'); } } addTag('Flutter'); // Tag "flutter" added. addTag('Dart'); // Tag "dart" added. addTag('Mobile'); // Tag "mobile" added. addTag('flutter'); // Tag "flutter" already exists. addTag('DART'); // Tag "dart" already exists. print('Tags: $articleTags'); // Tags: {flutter, dart, mobile} }

Visited Pages Tracker

dart
class PageTracker { final Set<String> _visited = {}; final List<String> _history = []; // ordered history with duplicates void visit(String page) { bool isNew = _visited.add(page); _history.add(page); if (isNew) { print('First visit to: $page'); } else { print('Revisiting: $page'); } } Set<String> get uniquePages => Set.unmodifiable(_visited); List<String> get fullHistory => List.unmodifiable(_history); int get uniquePageCount => _visited.length; int get totalVisits => _history.length; } void main() { var tracker = PageTracker(); tracker.visit('/home'); tracker.visit('/products'); tracker.visit('/about'); tracker.visit('/home'); // Revisit tracker.visit('/products'); // Revisit tracker.visit('/contact'); print('\nUnique pages visited: ${tracker.uniquePageCount}'); print('Total visits: ${tracker.totalVisits}'); print('Pages: ${tracker.uniquePages}'); }

Output:

First visit to: /home
First visit to: /products
First visit to: /about
Revisiting: /home
Revisiting: /products
First visit to: /contact

Unique pages visited: 4
Total visits: 6
Pages: {/home, /products, /about, /contact}

Summary

OperationMethodNotes
Create{}, Set<T>(), <T>{}Use <T>{} for empty Sets
Add oneadd(value)Returns bool — true if added
Add manyaddAll(iterable)Silently skips duplicates
Removeremove(value)Returns bool
Remove conditionalremoveWhere(test)Removes all matching
Check existencecontains(value)O(1) — very fast
Set mathunion(), intersection(), difference()Returns new Set
ConverttoList(), toSet()Use for deduplication

Sets are an underused but extremely efficient data structure. Whenever you find yourself checking membership frequently or needing uniqueness guarantees — reach for a Set.

WhatsApp