Dotnet Collections - Part 1
Dotnet Collections - Part 1
com
2
Table of Contents
§ Overview § Dictionary
‒ Sorted List
§ Array
‒ Sorted Dictionary
§ Collection Interfaces
§ Hash Set
§ List ‒ Sorted Set
‒ Linked-List
‒ Stack
‒ Queue
3
Overview
* 4
.NET collection history
.NET 1.0 .NET 2.0 .NET 3.0 .NET 4.0 .NET 4.5
5
Basic collection operations
Collection
Read Write
Replace items
6
Arrays
* 7
Introducing arrays
8
How to create a new array
Fails to compile
9
How is array of integers created?
numbers
Reference 0 i=0
0 i=1
0 i=2
0 i=3
0 i=4
10
How is array of strings created?
names
“A”
Reference i=0
“B”
i=1
i=2 “C”
i=3
“D”
i=4
“E”
11
How do arrays work?
X
Address of Remember C++ ?
the 1st item
i=0 S bytes
i=0
I want to add
i=1 more items
i=2 to the array.
i=3
i=4
13
Why do arrays have fixed length?
i=0
i=1
i=2
Not guaranteed to be free memory
i=3
i=4
X Add a new item here?
14
How to create a multi-dimensional array
15
How are rectangular arrays stored in memory?
i = [0,0] “D”
names
Reference i = [0,1]
i = [1,0] “B”
i = [1,1]
“E”
16
How are jagged arrays stored in memory?
18
Foreach iteration variable is read-only
Note
• Foreach interation variable (variable “item”) is read-only.
19
Foreach with array behind the scene
20
Why is foreach iteration variable read-only?
21
Array inheritance hierarchy
Object
Abstract class
Array
String[] Object[]
22
Array covariance
Note
• - Other collections don't have this feature.
• - However, IEnumerator<T> and IEnumerable<T> interfaces do have it.
23
Should you use array covariance?
objects[0] = 1;
Compiles successfully
but fails at run-time
Note
• - Array covariance is bad (damages type-safety of arrays).
• - Don't use it.
24
Copying arrays
source.CopyTo(target, 2);
Start index of target array
Note
• Array.Copy() will throw exception if “source” or “target” is null.
25
Reversing arrays
Note
• - Array methods work in-place (modify the source array).
• - LINQ methods return a new object (source array remains intact).
26
Sorting arrays
LINQ
Note
• String and number types (int, long, float, double, ...) have natural ordering.
• To compare other types, you must provide a comparer (IComparer<T>).
27
Finding elements using values
28
Finding elements using conditions
Search condition
var lastIndex = Array.FindLastIndex(numbers, n => n == 3);
29
Binary search
Note
• Should use BinarySearch() if array is large.
• Otherwise, use IndexOf().
30
Collection Interfaces
* 31
Non-generic collection interface hierarchy
IEnumerable Note
• These collections are obsolete.
• Should use generic versions instead.
ICollection
IList IDictionary
32
Generic collection interface hierarchy
IEnumerable
IEnumerable<T>
IList<T>
ISet<T>
33
Read-only collection interface hierarchy
IEnumerable
IEnumerable<T>
IReadOnlyList<T>
IReadOnlyCollection<T>
IReadOnlyDictionary<TKey, TValue>
34
IEnumerable<T>
IEnumerable<T>
GetEnumerator()
35
ICollection<T>
Add()
Remove()
Clear()
Contains()
CopyTo()
36
IList<T>
IEnumerable<T> ICollection<T>
I have basic
IList<T>
operations
of a list.
this[int]
IndexOf()
Insert()
RemoveAt()
37
IDictionary<TKey, TValue>
ICollection<T> IEnumerable<T>
IDictionary<TKey, TValue>
I have basic
this[TKey] operations
Keys of a dictionary.
Values
Add()
Remove()
ContainsKey()
TryGetValue()
38
ISet<T>
IEnumerable<T> ICollection<T>
39
Read-only collection interfaces
Count
IReadOnlyDictionary<TKey, TValue>
IReadOnlyList<T> this[TKey]
ContainsKey()
Keys
TryGetValue()
this[int] Values
40
Lists
* 41
Introducing List<T>
42
Create and use List<T>
list.Add(4);
list.AddRange(new[] { 6, 7, 8 });
“A”
Count = 2
“B”
Capacity = 4
null
null
Note
• - Capacity is the length of the underlying array.
• - Count is the number of values stored in array.
44
How does List<T> add new items?
names.Add(“C”);
“A”
“B” “C”
null
null
45
How does List<T> add new items?
O(1)
Big O notation
“A”
“B”
“C”
null
46
How does List<T> remove items?
names.Remove(“B”);
“A”
“B”
Copy
“C”
Copy
null
Note
• Shift all elements after “B” up one slot.
47
How does List<T> remove items?
“A”
“C”
“C”
Copy
null
48
How does List<T> remove items?
O(n)
“A”
“C”
null
null
49
How does List<T> insert items?
names.Insert(1, “B”);
“A” “B”
“C”
null
null
50
How does List<T> insert items?
names.Insert(1, “B”);
“A” “B”
“C”
Copy
null
null
Note
• Shift all elements from index 1 down one slot.
51
How does List<T> insert items?
“A” Replace
“B”
“C”
“C”
null
52
How does List<T> insert items?
O(n)
“A”
“B”
“C”
null
53
How does List<T> reallocate its array?
names.Add(“E”);
“A”
There's no more room
“B” to store a new element.
“C”
“D” ?
“E”
54
How does List<T> reallocate its array?
names.Add(“E”);
“A”
Double “B”
capacity “C”
“A” “E”
“D”
“B” Capacity = 8
Capacity = 4 null
“C” null
“D” null
null
55
Create a List<T> with capacity
Note
• - Use this when you know beforehand the capacity you'll need.
• - This will help List avoid reallocate its array continuously (better performance).
56
Introducing ReadOnlyCollection<T>
Note
• As its name suggests, ReadOnlyCollection<T> doesn't allow you to add or remove items.
57
Introducing Collection<T>
§ Implements IList<T>
58
Using Collection<T>
§ Not only for WPF but also for other type of projects
60
Using ObservableCollection<T>
61
Linked-Lists, Stacks, and Queues
* 62
Introducing Linked-List, Stack, and Queue
§ They are lists but without the ability to look up items using index
§ LinkedList<T>
‒ Doubly-linked list (has references to previous and next nodes)
‒ Very quick at adding or removing items
‒ But uses a lot of memory
§ Stack<T> (LIFO)
‒ Uses array under the hood
‒ Therefore, more efficient than LinkedList<T>
§ Queue<T> (FIFO)
‒ Also uses array under the hood
63
How does LinkedList<T> work?
First Last
Next
Previous LinkedListNode<T>
Note
• Each item in linked-list is a LinkedListNode<T>.
64
How to create a new LinkedList<T>
node = linkedList.AddLast(“B”);
Note
• - LinkedList<T> has no initializer, you must add items manually.
• - Every item is a LinkedListNode<T>.
65
Basic LinkedList<T> operations
linkedList.RemoveFirst();
Note
• Find()
- Find()isisnot
notefficient
efficientbecause
becauseit ithas
hastotosearch
searchthe
thewhole
wholelist.
list.
• Remove()
- Remove()also
alsohas
hastotosearch
searchthe
thewhole
wholelist.
list.
66
How does Stack<T> work?
“C”
stack.Push(“C”)
“B”
“A”
67
How does Stack<T> work?
“C”
“B”
“A”
68
How does Stack<T> work?
“C”
stack.Pop()
“B”
“A”
Note
• Stack<T> is LIFO (Last In First Out)
69
How to create and use Stack<T>
Note
• - Stack<T> uses array under the hood.
• - Like LinkedList<T>, Stack<T> has no initializer.
70
How does Queue<T> work?
“A” stack.Enqueue(“C”)
“B”
“C”
71
How does Queue<T> work?
“A”
“B”
“C”
72
How does Queue<T> work?
“A”
stack.Dequeue()
“B”
“C”
Note
• Queue<T> is FIFO (First In First Out)
73
How to create and use Queue<T>
Note
• - Queue<T> uses array under the hood.
• - It has no initializer.
74
Dictionaries
* 75
Introducing Dictionary<TKey, TValue>
76
Creating Dictionary<TKey, TValue>
Note
• - Dictionary has good performance.
• - Adding and removing items is fast.
77
Accessing values in Dictionary<TKey, TValue>
string employeeOfYear;
if (employees.TryGetValue(“GCS1000”, out employeeOfYear))
{
// Do something
}
Note
• Always use TryGetValue() to avoid exception if key doesn't exist.
78
How does Dictionary work?
Note
• This is a high-level overview of how hash table works.
79
How does Dictionary work?
Key: “GCS1000”
Value: “John Smith”
Note
• Buckets are implemented using array.
80
How does Dictionary work?
81
How does Dictionary work?
82
How does Dictionary work?
83
How does Dictionary work?
Key: “GCS1002”
Value: “James Doe”
84
Using StringComparer with Dictionary
Note
• - By default, strings are case-sensitive.
• - You can use a different comparer to ignore the casing.
• - In this case, we use StringComparer provided by .NET.
85
Implementing IEqualityComparer<T>
86
Implementing IEqualityComparer<T>
Note
• ReadOnlyDictionary doesn't have methods that modify the collection.
88
Introducing SortedList<TKey, TValue>
Note
• - Don't let its name fool you, SortedList is a dictionary.
• - It implements IDictionary<TKey, TValue> interface.
89
How does SortedList work?
SortedList<TKey, TValue>
TKey[] TValue[]
-------------- --------------
-------------- Sync --------------
-------------- --------------
90
Introducing SortedDictionary<TKey, TValue>
91
How does SortedDictionary work?
SortedDictionary<TKey, TValue>
Balanced tree
from SortedSet
92
Implementing IComparer<T>
§ Used to create Dictionary that can extract keys from its values
§ Demo: Create a dictionary that can extract keys from its values
94
Using KeyedCollection<TKey, TItem>
class Employee
{
public string Id { get; set; }
public string Name { get; set; }
}
95
How does KeyedCollection work?
KeyedCollection<TKey, TItem>
96
Sets
* 97
Introducing HashSet<T>
§ Implements ISet<T>
98
Set operations
§ Intersection
‒ Find values that are in both sets
§ Union
‒ Find values that are in either set
§ Difference
‒ Find values that are in the first set
§ Symmetric difference
‒ Find values that are in only one set
99
Using set operations with HashSet<T>
set1.IntersectWith(set2); // 1, 3
set1.UnionWith(set2); // 1, 2, 3, 4, 5, 7
set1.ExceptWith(set2); // 2, 4
set1.SymmetricExceptWith(set2); // 2, 4, 5, 7
Note
• - These methods work in-place (modify the source set).
• - Can also use LINQ methods for similar functionalities.
100
Set comparisons
§ IsProperSubsetOf()
§ IsProperSupersetOf() 2 4 2
1 3 1 3
101
Introducing SortedSet<T>
set.Add(“A”);
set.Remove(“A”);
102
How does SortedSet<T> work?
SortedSet<T>
Balanced tree
103
Dictionary vs HashSet
Dictionary HashSet
104
Summary
* 105
Summary
Modification
Collection Under the hood Access Lookup efficiency
efficiency
Index: O(1) - Contains():
List Array Index O(n)
O(n)
LinkedList Circular doubly linked list Contains(): O(n) O(1)
Stack Array Peek(): O(1) O(1)
Queue Array Peek(): O(1) O(1)
Dictionary Hash table Key Key: O(1) O(1)
SortedList Array Key Key: O(log n) O(n)
SortedDictionary Binary search tree Key Key: O(log n) O(log n)
HashSet Hash table Contains(): O(1) O(1)
SortedSet Binary search tree Contains(): O(log n) O(log n)
Faster Slower
O(1) O(log n) O(n)
106