Getting Started With the Swift Collections Package

Learn about three new data structures available in the Swift Collections package: Deque, OrderedSet and OrderedDictionary. By Felipe Laso-Marsetti.

Leave a rating/review
Download materials
Save for later
Share
You are currently viewing page 2 of 4 of this article. Click here to view the first page.

Comparing the Performance of Deque Versus Array

Using Deque to add items to the beginning of a large sequence is more performant. To compare the performance of inserting an element at the beginning of an Array versus a Deque, add the following code to the playground:

for number in 1...2000 {
  array.append("\(number)")
  deque.append("\(number)")
}

var start = Date()
array.insert("0", at: 0)
print(Date().timeIntervalSince(start))

start = Date()
deque.prepend("0")
print(Date().timeIntervalSince(start))

This code takes your existing sequences and adds two thousand elements into each. From there, you add an element at the beginning of each sequence and measure the time it takes.

Run your playground a couple of times and pay attention to the results. Notice how Deque is consistently faster than Array for this operation.

Knowing When to Use Deque

As you have seen, deques are very similar to arrays. Their main advantage lies in the increased efficiency when adding or removing to the beginning of the collection. However, as you’ve seen, the performance difference may be very small for a lot of cases. The only way to be sure that it’s worth using deques is to run performance testing, using Instruments, on a device. See our Instruments tutorial for more details.

All things considered, it’s great that Deque and Array are so similar because it’s quicker for you to learn and use Deque. You now have the option to use Deque when you need a more traditional double-ended queue.

In the next section, you’ll learn about a new type where the decision to use it or not is much more obvious.

Introducing OrderedSet

Here’s the major reason to rejoice about the Swift Collections package: OrderedSet!

Before this, it was frustrating to keep a unique list of items in a specific order in Swift, especially because that’s a common scenario. Think of an app that processes a store’s preorders. There can only be one preorder per customer. If you, Ray and I all want to preorder the next iPhone, Apple needs to know who placed the order first, second and last. While a Swift Array could work for this, you’d need to write extra code to prevent the user from adding duplicate items to the collection.

Set, the old alternative to Array, could maintain each element’s uniqueness, but it doesn’t maintain or guarantee the order. You could use a tuple or custom type to track the position or order, but this would get cumbersome, add extra code to your project and result in reduced performance compared to a proper, native set that maintains order.

Now, there’s a data structure that fills in both of those gaps: OrderedSet. It not only guarantees the uniqueness of elements, but it also maintains their order!

Ordered Set vs. Set

Working With OrderedSet

Open the Ordered Set page in the playground and add the following code at the very bottom:

var orderedSet = OrderedSet<String>()

Voilà! You’ll see an OrderedSet of Swift strings. Like other Swift Collections, you can create an ordered set using a literal like this:

var orderedSet: OrderedSet<String> = []

Now, to add items to your ordered set, add the following code to your playground:

orderedSet.append(customer2)
orderedSet.append(customer1)
orderedSet.append(customer3)
orderedSet

As with many other collections in Swift, append(_:) adds elements to the OrderedSet. The resulting ordered set looks like this:

["Andrea", "James", "Ray"]

Notice that the ordered set respects the order in which you added the elements.

Checking for Equality Using OrderedSet

With OrderedSet, checking for equality against another collection works differently than with a regular Set. Set checks to ensure that both collections contain the exact same elements regardless of the order, whereas OrderedSet checks that the elements are the same and appear in the same order.

Add the following code to your playground to test this:

orderedSet == [customer2, customer1, customer3]

Compare that to the example code applied to set:

set == [customer1, customer2, customer3]

Notice that Set‘s elements were a different order than the collection you compared, but it still returned true when checking for equality.

Next, you’ll learn how to add an object to an existing OrderedSet.

Adding Elements to an Existing OrderedSet

To add an object when working with Set, you only need to specify an element to add to the collection. But with OrderedSet, you also need to include an index because it keeps track of the order of elements. To do this, add the following code to your playground:

var result = orderedSet.insert(customer4, at: orderedSet.startIndex)
orderedSet

This is the resulting collection:

["Elena", "Andrea", "James", "Ray"]

This code adds Elena to the beginning of your ordered set.

Next, you’ll learn how to remove an element.

Removing Elements From an OrderedSet

You can also remove elements from an ordered set using remove(). Add the following code to your playground:

orderedSet.remove(customer1)
orderedSet

Here, you specified the element you want to remove and let OrderedSet take care of it. You don’t have to worry about figuring out the index of the element you want to remove.

Unlike Set, OrderedSet implements most of SetAlgebra, but not all of it. This can be important should your project require it for backward compatibility with your existing code.

To try using SetAlgebra with OrderedSet, add the following code to your playground:

orderedSet.isSubset(of: allCustomers)

The result will be true, because this method checks to see if OrderedSet is a subset of allCustomers, not if the order of the elements is the same.

Knowing When to Use OrderedSet

Use your newfound best friend, OrderedSet, when you need to maintain both the uniqueness and the order of the elements in your collection. Otherwise, you can continue to use Set. This is especially true if you:

  • Rely on SetAlgebra‘s’ operations and compliance
  • Need to use elements to work with existing functions that don’t support OrderedSet.

Now, you’ll learn about how OrderedSet works to further help in your decision-making process.

Equality between two ordered sets happens when both the elements and their order are the same. In contrast, a Set only needs both sets to contain the same elements to have equality.

At the end of the previous section, you saw that OrderedSet implements most of SetAlgebra, but doesn’t conform to it. The documentation for Swift Collections mentions that OrderedSet is “incompatible with SetAlgebra’s documented semantic requirements” due to the way it checks the order of the elements when it compares for equality.

Operations that return an ordered set will usually take into account the original order of the elements. However, some, like isSubset(of:), do not.

If your code needs SetAlgebra, you could still potentially work with OrderedSet because it does have an unordered property that returns an unordered collection of your elements. The unordered collection it returns is of type UnorderedView.

Now, it’s time to move on to the performance side of OrderedSet.

As with with Set, the performance of your code will depend on the quality of hashing that the elements of your OrderedSet implement. This is great news because you don’t have to pay a performance penalty for using OrderedSet instead of Set. This differs from the penalty you pay for using Deque instead of Array in scenarios that the latter could handle gracefully.