Skip to main content

Set<E>

A Set<E> is a collection of unique elements — no duplicates allowed. Sets excel at membership testing, deduplication, and mathematical set operations like union and intersection.


When to Use​

✅ Use Set<E> when you need to:

  • Guarantee uniqueness (no duplicate elements)
  • Fast O(1) membership testing (contains)
  • Perform set operations: union, intersection, difference
  • Deduplicate a List

❌ Don't use Set<E> when you need to:

  • Access elements by index (sets have no index)
  • Preserve duplicates → use List<E>
  • Key-value pairs → use Map<K,V>
  • Sorted unique elements → use SplayTreeSet<E>

Memory Layout​

The default Set literal creates a LinkedHashSet, which combines a hash table for O(1) lookup with a doubly-linked list to preserve insertion order.


Syntax​

// Set literal (creates a LinkedHashSet)
var fruits = {'apple', 'banana', 'cherry'};

// Typed
Set<String> typed = {'apple', 'banana'};
var typed2 = <String>{'apple', 'banana'};

// IMPORTANT: {} alone is an empty Map, NOT a Set!
var emptyMap = {}; // Map<dynamic, dynamic>
var emptySet = <String>{}; // ✅ Empty Set
warning

{} creates an empty Map, not a Set! Always use <Type>{} for an empty Set.


Constructors​

Set() / Set.identity()​

The default Set() factory constructor creates a LinkedHashSet (insertion-ordered, hash-based).

var s = Set<int>();
s.add(1); s.add(2); s.add(3);
print(s); // {1, 2, 3}

Set.identity() uses identity (identical()) instead of == and hashCode for comparison.

var s = Set<List<int>>.identity();
var list1 = [1, 2, 3];
var list2 = [1, 2, 3];
s.add(list1);
print(s.contains(list2)); // false (different object)
print(s.contains(list1)); // true (same object)

Set.of(Iterable<E> elements)​

Creates a new LinkedHashSet containing the given elements, discarding duplicates.

var list = [1, 2, 2, 3, 3, 3, 4];
var set = Set.of(list);
print(set); // {1, 2, 3, 4}

Set.from(Iterable elements)​

Like Set.of but accepts Iterable<dynamic>. Less type-safe; prefer Set.of.

Set.unmodifiable(Iterable<E> elements)​

Creates an unmodifiable set. Any mutation attempt throws UnsupportedError.

var immutable = Set.unmodifiable({1, 2, 3});
immutable.add(4); // ❌ UnsupportedError

Key Properties​

PropertyTypeDescription
lengthintNumber of elements
isEmptyboolTrue if the set has no elements
isNotEmptyboolTrue if the set has elements
firstEFirst element in iteration order
lastELast element in iteration order
singleEOnly element; throws if 0 or 2+
iteratorIterator<E>For for-in loops

Methods — Complete Reference​

Adding Elements​

add(E value) → bool​

Adds value. Returns true if added (new element), false if already present.

var s = <int>{1, 2, 3};
print(s.add(4)); // true → s is {1, 2, 3, 4}
print(s.add(2)); // false → duplicate, s unchanged

addAll(Iterable<E> elements)​

Adds all elements from the iterable, skipping duplicates.

var s = {1, 2, 3};
s.addAll([2, 3, 4, 5]);
print(s); // {1, 2, 3, 4, 5}

Removing Elements​

remove(Object? value) → bool​

Removes value. Returns true if it was present.

var s = {1, 2, 3};
print(s.remove(2)); // true → {1, 3}
print(s.remove(9)); // false → no change

removeAll(Iterable<Object?> elements)​

Removes all elements in the given iterable.

var s = {1, 2, 3, 4, 5};
s.removeAll([2, 4]);
print(s); // {1, 3, 5}

removeWhere(bool Function(E) test)​

Removes all elements matching the predicate.

var s = {1, 2, 3, 4, 5, 6};
s.removeWhere((n) => n.isEven);
print(s); // {1, 3, 5}

retainAll(Iterable<Object?> elements)​

Removes all elements not in the given iterable (keeps only common elements — intersection-in-place).

var s = {1, 2, 3, 4, 5};
s.retainAll([2, 4, 6]);
print(s); // {2, 4}

retainWhere(bool Function(E) test)​

Removes all elements that do NOT match the predicate.

var s = {1, 2, 3, 4, 5};
s.retainWhere((n) => n > 2);
print(s); // {3, 4, 5}

clear()​

Removes all elements.

var s = {1, 2, 3};
s.clear();
print(s); // {}

Searching & Testing​

contains(Object? value) → bool​

Returns true if the set contains the element. O(1) average for hash-based sets.

var s = {'apple', 'banana', 'cherry'};
print(s.contains('banana')); // true
print(s.contains('mango')); // false

containsAll(Iterable<Object?> other) → bool​

Returns true if the set contains every element in other.

var s = {1, 2, 3, 4, 5};
print(s.containsAll([1, 3, 5])); // true
print(s.containsAll([1, 6])); // false

any(bool Function(E) test) → bool​

var s = {1, 2, 3, 4};
print(s.any((n) => n > 3)); // true

every(bool Function(E) test) → bool​

var s = {2, 4, 6};
print(s.every((n) => n.isEven)); // true

Set Operations​

These are the core mathematical set operations. Each returns a new Set.

union(Set<E> other) → Set<E>​

Returns all elements in this or the other set (logical OR).

var a = {1, 2, 3, 4, 5};
var b = {3, 4, 5, 6, 7};
print(a.union(b)); // {1, 2, 3, 4, 5, 6, 7}

intersection(Set<Object?> other) → Set<E>​

Returns elements present in both sets (logical AND).

var a = {1, 2, 3, 4, 5};
var b = {3, 4, 5, 6, 7};
print(a.intersection(b)); // {3, 4, 5}

difference(Set<Object?> other) → Set<E>​

Returns elements in this set but not in other.

var a = {1, 2, 3, 4, 5};
var b = {3, 4, 5, 6, 7};
print(a.difference(b)); // {1, 2}
print(b.difference(a)); // {6, 7}

Conversion​

toList({bool growable = true}) → List<E>​

var s = {3, 1, 4, 1, 5, 9, 2, 6};
var list = s.toList();
print(list); // [3, 1, 4, 5, 9, 2, 6] (no duplicates)

toSet() → Set<E>​

Returns a copy of this set as a new Set.

var s = {1, 2, 3};
var copy = s.toSet();
copy.add(4);
print(s); // {1, 2, 3} — original unchanged
print(copy); // {1, 2, 3, 4}

map<T>(T Function(E) f) → Iterable<T>​

var s = {1, 2, 3};
print(s.map((n) => n * 2).toSet()); // {2, 4, 6}

where(bool Function(E) test) → Iterable<E>​

var s = {1, 2, 3, 4, 5};
print(s.where((n) => n.isOdd).toSet()); // {1, 3, 5}

join([String separator = '']) → String​

print({'a', 'b', 'c'}.join(', ')); // a, b, c

Performance & Complexity​

OperationHashSetLinkedHashSetSplayTreeSet
add()O(1) avgO(1) avgO(log n)
remove()O(1) avgO(1) avgO(log n)
contains()O(1) avgO(1) avgO(log n)
union()O(n + m)O(n + m)O(n log n)
intersection()O(n)O(n)O(n log n)
IterationO(n)O(n)O(n)
OrderNoneInsertionSorted

Real-World Examples​

Example 1: Deduplicating Tags​

List<String> rawTags = ['flutter', 'dart', 'flutter', 'mobile', 'dart', 'dart'];
Set<String> uniqueTags = rawTags.toSet();
print(uniqueTags); // {flutter, dart, mobile}

Example 2: Permission System​

class User {
final String name;
final Set<String> permissions;

User(this.name, this.permissions);

bool can(String action) => permissions.contains(action);

bool canAll(Iterable<String> actions) => permissions.containsAll(actions);
}

var admin = User('Alice', {'read', 'write', 'delete', 'admin'});
var viewer = User('Bob', {'read'});

print(admin.can('delete')); // true
print(viewer.can('write')); // false
print(admin.canAll(['read', 'write'])); // true

// Find shared permissions
var shared = admin.permissions.intersection(viewer.permissions);
print(shared); // {read}

Example 3: Search History (Unique, Ordered)​

class SearchHistory {
final LinkedHashSet<String> _history = LinkedHashSet();
static const int maxEntries = 10;

void add(String query) {
_history.remove(query); // Move to end if exists
_history.add(query);
while (_history.length > maxEntries) {
_history.remove(_history.first);
}
}

List<String> get recent => _history.toList().reversed.toList();
}

Example 4: Graph — Visited Nodes​

// BFS using a Set to track visited nodes
Map<int, List<int>> graph = {
1: [2, 3],
2: [4, 5],
3: [5, 6],
4: [],
5: [6],
6: [],
};

List<int> bfs(int start) {
final visited = <int>{};
final queue = Queue<int>();
final result = <int>[];

queue.add(start);
visited.add(start);

while (queue.isNotEmpty) {
final node = queue.removeFirst();
result.add(node);
for (final neighbor in graph[node] ?? []) {
if (!visited.contains(neighbor)) {
visited.add(neighbor);
queue.add(neighbor);
}
}
}
return result;
}

import 'dart:collection';
print(bfs(1)); // [1, 2, 3, 4, 5, 6]

Flutter Examples​

Multi-select with a Set​

class MultiSelectList extends StatefulWidget {
final List<String> items;
const MultiSelectList({required this.items, super.key});


State<MultiSelectList> createState() => _MultiSelectListState();
}

class _MultiSelectListState extends State<MultiSelectList> {
final Set<String> _selected = {};


Widget build(BuildContext context) {
return Column(children: [
...widget.items.map((item) => CheckboxListTile(
title: Text(item),
value: _selected.contains(item),
onChanged: (checked) => setState(() =>
checked! ? _selected.add(item) : _selected.remove(item)),
)),
Text('Selected: ${_selected.join(', ')}'),
]);
}
}

Common Mistakes​

❌ Using {} for an empty set​

var s = {}; // ❌ This is Map<dynamic, dynamic>!
var s = <int>{}; // ✅ This is Set<int>

❌ Expecting a specific iteration order from HashSet​

import 'dart:collection';
var hs = HashSet.of([3, 1, 4, 1, 5]);
// ❌ Don't assume order — HashSet is unordered
for (var n in hs) print(n); // order is undefined

// ✅ Use LinkedHashSet or sort the result
var sorted = hs.toList()..sort();

❌ Using List.contains() for large membership tests​

var list = List.generate(10000, (i) => i);

// ❌ O(n) every call — very slow for many lookups
if (list.contains(9999)) { ... }

// ✅ Convert to Set once, then O(1) lookups
var set = list.toSet();
if (set.contains(9999)) { ... }

❌ Comparing sets with ==​

var a = {1, 2, 3};
var b = {1, 2, 3};
print(a == b); // false — different object references

// ✅ Use SetEquality from package:collection
import 'package:collection/collection.dart';
print(const SetEquality().equals(a, b)); // true

// ✅ Or check containsAll in both directions
print(a.containsAll(b) && b.containsAll(a)); // true

Best Practices​

  • Use Set for membership testing instead of List when the collection is large.
  • Use Set.of(list) for deduplication — it's one-liner and idiomatic.
  • Prefer LinkedHashSet (the default) when you need predictable iteration order.
  • Use HashSet when order doesn't matter and you want maximum performance.
  • Use SplayTreeSet when you need sorted iteration.
  • Use const {...} for compile-time constant sets.

Comparison with Similar Collections​

FeatureSet<E>List<E>HashSet<E>SplayTreeSet<E>
Unique✅❌✅✅
OrderedInsertionPosition❌Sorted
Index access❌✅❌❌
contains()O(1)O(n)O(1)O(log n)
Importcorecoredart:collectiondart:collection