Watch the video (8 min)
On this page22 sections
  1. Prerequisites
  2. Connection With Previous Lectures
  3. Learning Objectives
  4. 1. Comparing Two Groups
  5. 2. union — Everyone in Either Set
  6. 3. intersection — Only the Shared Values
  7. 4. difference — In This One, Not That One
  8. 5. The Original Sets Do Not Change
  9. 6. containsAll — Is One Set Inside Another?
  10. 7. addAll, removeAll, retainAll — Change the Set Itself
  11. 8. where and map on a Set
  12. 9. Mixing Sets and Lists
  13. 10. A Real-World Example
  14. Code Examples
  15. Common Beginner Mistakes
  16. Best Practices
  17. Mini Challenge
  18. Practice Questions
  19. Practice Answers
  20. Quick Revision
  21. Key Takeaways
  22. What's Next?

Lecture 48 — Set Operations

Category8 — Sets & Maps
Lecture048 of 140
Estimated video length8 min
TargetDart 3.12.2
LevelBeginner

One set answers "is this value here?". Two sets answer better questions: who is in both clubs, who is in either, and what is missing. Dart answers each in one call.

Contents

Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways

Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.


Prerequisites

Students should already understand, from Lectures 001–047:

  • final and const variables (Lecture 006)
  • arrow functions (Lecture 034)
  • addAll and removeWhere on lists (Lecture 041)
  • where, map, and toList (Lecture 043)
  • Set<T> literals, add, remove, contains, and removing duplicates (Lecture 047)

Connection With Previous Lectures

In Lecture 047 we asked one set one question at a time:

dart
chess.contains('Sara');

Now the school wants to know which students are in the chess club and the football club. With only contains, we would loop over one set and check every name against the other. The question is about two whole groups, so we need operations that work on two whole sets.


Learning Objectives

By the end of this lecture you will be able to:

  • Combine two sets with union
  • Find the shared values of two sets with intersection
  • Find what one set has and another lacks with difference
  • Check whether one set sits inside another with containsAll
  • Change a set in place with addAll, removeAll, and retainAll
  • Use where and map on a set and turn the result back into a set
  • Mix sets and lists safely in these operations
  • Solve everyday problems: shared friends, club members, missing items

1. Comparing Two Groups

Every operation in this lecture compares two sets, so it helps to picture them.

Analogy — draw two overlapping circles, one per club. The overlap holds the students in both. Everything inside either circle is everyone. One circle minus the overlap is "only in this club".

dart
void main() {
  Set<String> chess = {'Ali', 'Sara', 'Zayan'};
  Set<String> football = {'Sara', 'Omar', 'Zayan', 'Hina'};
  print(chess);
  print(football);
}
output
{Ali, Sara, Zayan}
{Sara, Omar, Zayan, Hina}

We use these two clubs throughout the lesson. Sara and Zayan are in both.


2. union — Everyone in Either Set

a.union(b) returns a new set with every value from a and every value from b. A value in both appears once, because a set never holds duplicates.

dart
void main() {
  Set<String> chess = {'Ali', 'Sara', 'Zayan'};
  Set<String> football = {'Sara', 'Omar', 'Zayan', 'Hina'};
  print(chess.union(football));
}
output
{Ali, Sara, Zayan, Omar, Hina}

Values from chess come first, then the new ones from football.


3. intersection — Only the Shared Values

a.intersection(b) returns a new set with only the values that are in both sets.

dart
void main() {
  Set<String> chess = {'Ali', 'Sara', 'Zayan'};
  Set<String> football = {'Sara', 'Omar', 'Zayan', 'Hina'};
  print(chess.intersection(football));
}
output
{Sara, Zayan}

This is the overlap of the two circles. If nothing is shared, the result is the empty set {}.


4. difference — In This One, Not That One

a.difference(b) returns the values in a that are not in b. Order matters: swapping the sets asks a different question.

dart
void main() {
  Set<String> chess = {'Ali', 'Sara', 'Zayan'};
  Set<String> football = {'Sara', 'Omar', 'Zayan', 'Hina'};
  print(chess.difference(football));
  print(football.difference(chess));
}
output
{Ali}
{Omar, Hina}

Read it as "chess minus football": only Ali plays chess without playing football.


5. The Original Sets Do Not Change

union, intersection, and difference build a new set and leave both originals alone. Store the result if you need it.

dart
void main() {
  Set<String> chess = {'Ali', 'Sara', 'Zayan'};
  Set<String> football = {'Sara', 'Omar'};
  Set<String> everyone = chess.union(football);
  print(everyone);
  print(chess);
}
output
{Ali, Sara, Zayan, Omar}
{Ali, Sara, Zayan}

Because nothing changes, these three also work on const sets.


6. containsAll — Is One Set Inside Another?

a.containsAll(b) returns true when every value of b is also in a. In other words, b is a subset of a. Dart has no separate isSubset method; containsAll is how you ask.

dart
void main() {
  Set<String> chess = {'Ali', 'Sara', 'Zayan'};
  print(chess.containsAll({'Ali', 'Zayan'}));
  print(chess.containsAll({'Ali', 'Omar'}));
}
output
true
false

To ask "is small inside big?", write big.containsAll(small). The bigger set goes first.


7. addAll, removeAll, retainAll — Change the Set Itself

These three change the set they are called on and return nothing. They are the in-place versions of union, difference, and intersection.

dart
void main() {
  Set<String> cart = {'milk', 'bread', 'eggs'};
  cart.addAll({'rice', 'milk'});
  print(cart);
  cart.removeAll({'bread', 'tea'});
  print(cart);
  cart.retainAll({'milk', 'rice', 'sugar'});
  print(cart);
}
output
{milk, bread, eggs, rice}
{milk, eggs, rice}
{milk, rice}

addAll skips the duplicate 'milk'. removeAll ignores 'tea', which was never there. retainAll keeps only the values that also appear in its argument.

New set (originals unchanged)Changes the set in place
a.union(b)a.addAll(b)
a.difference(b)a.removeAll(b)
a.intersection(b)a.retainAll(b)

8. where and map on a Set

Sets have the same where and map you used on lists in Lecture 043. Both return an Iterable (printed with round brackets), so add .toSet() to get a set back.

dart
void main() {
  Set<String> football = {'Sara', 'Omar', 'Zayan', 'Hina'};
  var shortNames = football.where((name) => name.length == 4).toSet();
  print(shortNames);

  Set<int> marks = {80, 75, 90};
  print(marks.map((mark) => mark >= 75 ? 'pass' : 'fail'));
  print(marks.map((mark) => mark >= 75 ? 'pass' : 'fail').toSet());
}
output
{Sara, Omar, Hina}
(pass, pass, pass)
{pass}

Watch the last line: map can produce repeated values, and .toSet() collapses them into one. Iterable itself is covered in Lecture 046 — Collection Features.


9. Mixing Sets and Lists

containsAll, addAll, removeAll, and retainAll accept a list as well as a set. union, intersection, and difference need a set, so convert a list with .toSet() first.

dart
void main() {
  Set<String> pantry = {'rice', 'salt', 'oil'};
  List<String> recipe = ['rice', 'oil', 'oil'];
  print(pantry.containsAll(recipe));
  print(pantry.union(['sugar'].toSet()));
}
output
true
{rice, salt, oil, sugar}

10. A Real-World Example

Sara has a shopping list and a set of items already at home. What must she buy, and is anything at home not on the list?

dart
void main() {
  List<String> shoppingList = ['milk', 'eggs', 'bread', 'milk', 'tea'];
  Set<String> atHome = {'eggs', 'tea', 'butter'};

  Set<String> needed = shoppingList.toSet();
  Set<String> toBuy = needed.difference(atHome);
  Set<String> alreadyHave = needed.intersection(atHome);
  Set<String> extra = atHome.difference(needed);

  print('To buy: $toBuy');
  print('Already have: $alreadyHave');
  print('Not on the list: $extra');
  print('Nothing to buy: ${atHome.containsAll(needed)}');
}
output
To buy: {milk, bread}
Already have: {eggs, tea}
Not on the list: {butter}
Nothing to buy: false

The list's duplicate 'milk' disappears in toSet(), then each question is one operation.


Code Examples

Example 1 — Union of Two Number Sets

dart
void main() {
  Set<int> a = {1, 2, 3};
  Set<int> b = {3, 4, 5};
  print(a.union(b));
}
output
{1, 2, 3, 4, 5}

Example 2 — Intersection

dart
void main() {
  Set<int> a = {1, 2, 3, 4};
  Set<int> b = {3, 4, 5};
  print(a.intersection(b));
}
output
{3, 4}

Example 3 — Difference Both Ways

dart
void main() {
  Set<int> a = {1, 2, 3, 4};
  Set<int> b = {3, 4, 5};
  print(a.difference(b));
  print(b.difference(a));
}
output
{1, 2}
{5}

Example 4 — Nothing in Common

dart
void main() {
  Set<String> morning = {'Ali', 'Sara'};
  Set<String> evening = {'Zayan', 'Hina'};
  Set<String> both = morning.intersection(evening);
  print(both);
  print(both.isEmpty);
}
output
{}
true

Example 5 — Subset Check

dart
void main() {
  Set<String> skills = {'Dart', 'Git', 'SQL'};
  print(skills.containsAll({'Dart', 'Git'}));
  print(skills.containsAll({'Dart', 'Java'}));
}
output
true
false

Example 6 — In-Place Changes

dart
void main() {
  Set<int> numbers = {1, 2, 3};
  numbers.addAll([3, 4]);
  numbers.removeAll([1]);
  numbers.retainAll({2, 4, 6});
  print(numbers);
}
output
{2, 4}

addAll gives {1, 2, 3, 4}, removeAll gives {2, 3, 4}, and retainAll keeps 2 and 4.

Example 7 — Common Friends

dart
void main() {
  Set<String> aliFriends = {'Sara', 'Omar', 'Hina', 'Bilal'};
  Set<String> zayanFriends = {'Hina', 'Sara', 'Usman'};
  Set<String> common = aliFriends.intersection(zayanFriends);
  print('Common friends: $common');
  print('Count: ${common.length}');
}
output
Common friends: {Sara, Hina}
Count: 2

Example 8 — Student Marks: Who Passed Both Tests?

dart
void main() {
  Set<String> passedMath = {'Ali', 'Sara', 'Zayan'};
  Set<String> passedScience = {'Sara', 'Zayan', 'Omar'};
  print('Passed both: ${passedMath.intersection(passedScience)}');
  print('Passed at least one: ${passedMath.union(passedScience)}');
  print('Math only: ${passedMath.difference(passedScience)}');
}
output
Passed both: {Sara, Zayan}
Passed at least one: {Ali, Sara, Zayan, Omar}
Math only: {Ali}

Example 9 — Shopping: Items Out of Stock

dart
void main() {
  Set<String> order = {'pen', 'notebook', 'ruler', 'eraser'};
  Set<String> inStock = {'pen', 'eraser', 'stapler'};
  Set<String> missing = order.difference(inStock);
  print('Missing: $missing');
  print('Can ship now: ${inStock.containsAll(order)}');
}
output
Missing: {notebook, ruler}
Can ship now: false

Example 10 — Temperature: Hot Days in Both Cities

dart
void main() {
  Set<int> lahoreHot = {1, 2, 5, 6};
  Set<int> karachiHot = {2, 3, 5};
  Set<int> both = lahoreHot.intersection(karachiHot);
  var labels = both.map((day) => 'Day $day').toSet();
  print(labels);
}
output
{Day 2, Day 5}

The sets hold day numbers. intersection finds the shared days, then map turns each number into a label.


Common Beginner Mistakes

1. Expecting union to change the set

dart
chess.union(football); // result thrown away
print(chess);          // still the old chess club

union, intersection, and difference return a new set. Store it, or use addAll, retainAll, or removeAll to change the set itself.

2. Reading difference backwards

a.difference(b) is "in a, not in b". To find what is missing from stock, write order.difference(inStock), not inStock.difference(order).

3. Storing a where result in a Set variable

dart
void main() {
  Set<String> names = {'Ali', 'Sara'};
  Set<String> short = names.where((n) => n.length == 3); // ✗
  print(short);
}
output
Error: A value of type 'Iterable<String>' can't be assigned to a variable of type 'Set<String>'.

Add .toSet() at the end.

4. Passing a list to union

dart
void main() {
  Set<String> names = {'Ali'};
  print(names.union(['Sara'])); // ✗
}
output
Error: The argument type 'List<String>' can't be assigned to the parameter type 'Set<String>'.

Write names.union(['Sara'].toSet()), or use addAll(['Sara']) to change names.

5. Combining sets of different types

dart
void main() {
  Set<int> ids = {1, 2};
  Set<String> names = {'Ali'};
  print(ids.union(names)); // ✗
}
output
Error: The argument type 'Set<String>' can't be assigned to the parameter type 'Set<int>'.

6. Changing a const set in place

dart
void main() {
  const Set<String> days = {'Mon', 'Tue'};
  days.addAll({'Wed'}); // ✗ compiles, then crashes
}
output
Unhandled exception:
Unsupported operation: Cannot change an unmodifiable set

Use final for a set you will change. union on a const set is fine.

7. Putting the sets the wrong way round in containsAll

big.containsAll(small) asks whether small is inside big. Swapping them asks the opposite.


Best Practices

  • Name results by their meaning: common, toBuy, missing, not result.
  • Use union / intersection / difference when you still need the originals.
  • Use addAll / retainAll / removeAll when the set should really change.
  • Read a.difference(b) aloud as "a minus b" before you run it.
  • End where and map with .toSet() when you need a set back.
  • Convert a list with .toSet() before comparing it with a set.

Mini Challenge

Ali's class enrolled {'Ali', 'Sara', 'Zayan', 'Omar'}. Today's attendance list was ['Sara', 'Ali', 'Sara', 'Hina'] (Sara was scanned twice, and Hina is a visitor). Print who was absent, who attended, and who attended without being enrolled.

output
Absent: {Zayan, Omar}
Attended: {Ali, Sara}
Visitors: {Hina}

Try it yourself before opening the solution.

Show solution
dart
void main() {
  Set<String> enrolled = {'Ali', 'Sara', 'Zayan', 'Omar'};
  Set<String> present = ['Sara', 'Ali', 'Sara', 'Hina'].toSet();
  print('Absent: ${enrolled.difference(present)}');
  print('Attended: ${enrolled.intersection(present)}');
  print('Visitors: ${present.difference(enrolled)}');
}
output
Absent: {Zayan, Omar}
Attended: {Ali, Sara}
Visitors: {Hina}

Practice Questions

Work through these in order — they run from beginner to application to challenge. Every question gives you exact values, so you can compare your output with the answers.

Beginner

  1. Print the union of {1, 2, 3} and {2, 3, 4}.
  2. Print the intersection of {'red', 'blue', 'green'} and {'blue', 'yellow', 'green'}.
  3. Print {10, 20, 30, 40} minus {20, 40}.

Application

  1. Sara knows {'Dart', 'Git'}; a job needs {'Dart', 'Git', 'SQL'}. Print whether she has every required skill, then print the skills she is missing.
  2. Start with final tags = {'news', 'sport'}. Use addAll with the list ['sport', 'tech'], then print tags.
  3. Start with final cart = {'pen', 'ink', 'pad', 'tape'}. Remove {'ink', 'tape'} in place, then print cart.
  4. From {45, 80, 62, 90, 30} keep only marks of 50 or more using where, as a set, and print it.
  5. Ali's friends are {'Sara', 'Omar', 'Hina'} and Zayan's are {'Hina', 'Usman', 'Sara'}. Print their common friends and how many there are, as Common: … (2).

Challenge

  1. Map the set {3, 7, 8, 10} to 'odd' or 'even' and print the result as a set.
  2. A recipe needs ['flour', 'sugar', 'eggs', 'sugar']. The kitchen has {'flour', 'salt', 'eggs'}. Print To buy: …, then Unused: … for items in the kitchen the recipe does not need.

Practice Answers

Question 1 — Solution

dart
void main() {
  print({1, 2, 3}.union({2, 3, 4}));
}
output
{1, 2, 3, 4}

Question 2 — Solution

dart
void main() {
  Set<String> a = {'red', 'blue', 'green'};
  Set<String> b = {'blue', 'yellow', 'green'};
  print(a.intersection(b));
}
output
{blue, green}

Question 3 — Solution

dart
void main() {
  print({10, 20, 30, 40}.difference({20, 40}));
}
output
{10, 30}

Question 4 — Solution

dart
void main() {
  Set<String> sara = {'Dart', 'Git'};
  Set<String> job = {'Dart', 'Git', 'SQL'};
  print(sara.containsAll(job));
  print(job.difference(sara));
}
output
false
{SQL}

Question 5 — Solution

dart
void main() {
  final tags = {'news', 'sport'};
  tags.addAll(['sport', 'tech']);
  print(tags);
}
output
{news, sport, tech}

Question 6 — Solution

dart
void main() {
  final cart = {'pen', 'ink', 'pad', 'tape'};
  cart.removeAll({'ink', 'tape'});
  print(cart);
}
output
{pen, pad}

Question 7 — Solution

dart
void main() {
  Set<int> marks = {45, 80, 62, 90, 30};
  Set<int> passed = marks.where((mark) => mark >= 50).toSet();
  print(passed);
}
output
{80, 62, 90}

Question 8 — Solution

dart
void main() {
  Set<String> ali = {'Sara', 'Omar', 'Hina'};
  Set<String> zayan = {'Hina', 'Usman', 'Sara'};
  Set<String> common = ali.intersection(zayan);
  print('Common: $common (${common.length})');
}
output
Common: {Sara, Hina} (2)

The order follows ali, the set intersection was called on.

Question 9 — Solution

dart
void main() {
  Set<int> numbers = {3, 7, 8, 10};
  print(numbers.map((n) => n % 2 == 0 ? 'even' : 'odd').toSet());
}
output
{odd, even}

Four numbers give four labels, but only two different ones survive toSet().

Question 10 — Solution

dart
void main() {
  Set<String> needed = ['flour', 'sugar', 'eggs', 'sugar'].toSet();
  Set<String> kitchen = {'flour', 'salt', 'eggs'};
  print('To buy: ${needed.difference(kitchen)}');
  print('Unused: ${kitchen.difference(needed)}');
}
output
To buy: {sugar}
Unused: {salt}

Quick Revision

  1. What does union return?
  2. Which operation finds the values two sets share?
  3. Why is a.difference(b) usually different from b.difference(a)?
  4. How do you check that one set is a subset of another?
  5. What is the in-place version of intersection?
  6. Do union and intersection change the original sets?
  7. What does where return on a set, and how do you get a set back?
  8. Why can map(...).toSet() have fewer values than the original set?

Key Takeaways

  • union = everything in either set; intersection = only what both share.
  • a.difference(b) = in a but not in b; the order of the sets matters.
  • These three return a new set and leave the originals unchanged.
  • big.containsAll(small) checks whether small is a subset of big.
  • addAll, removeAll, and retainAll change the set itself and return nothing.
  • where and map return an Iterable; add .toSet() to get a set.
  • union, intersection, and difference need a set — convert lists with .toSet().
  • A const set cannot be changed in place; use final for sets that change.

What's Next?

Lecture 049 — Maps. Sets tell us who is in a group, but not anything about them. Sara is in the chess club — what is her rating? Next we meet maps, which store each key together with a value, such as a name with a mark or a product with its price.


Video lecture

Subscribe
Placeholder video — the real recording isn't linked yet.