I have an array (or dictionary) and need to clear it. Performance wise, is it better to removeAll()
or create a new instance?
var things = [Thing]()
// Need to clear things
things.removeAll()
// or
things = [Thing]()
Array is faster than set in terms of initialization. Set is slower than an array in terms of initialization because it uses a hash process. The array allows to store duplicate elements in it. Set doesn't allow to store duplicate elements in it.
Swift provides three primary collection types, known as arrays, sets, and dictionaries, for storing collections of values. Arrays are ordered collections of values. Sets are unordered collections of unique values. Dictionaries are unordered collections of key-value associations.
There is no order. Dictionaries in Swift are an unordered collection type. The order in which the values will be returned cannot be determined.
(I accidentally misread your question and looked it up for Dictionary
, see below for Array
)
thing = [String : Thing]()
vs. thing.removeAll()
Now that Swift is open-source, we can have a look at whether those two statements actually do something different.
After digging through the source I found the initialiser for a Dictionary
here:
public init() {
self = Dictionary<Key, Value>(minimumCapacity: 0)
}
/// Create a dictionary with at least the given number of
/// elements worth of storage. The actual capacity will be the
/// smallest power of 2 that's >= `minimumCapacity`.
public init(minimumCapacity: Int) {
_variantStorage =
.Native(_NativeStorage.Owner(minimumCapacity: minimumCapacity))
}
As you can see, the underlying storage, which is the only property, gets assigned on initialisation.
Now let's have a look at removeAll()
from here:
internal mutating func removeAll(keepCapacity keepCapacity: Bool) {
if count == 0 {
return
}
if !keepCapacity {
self = .Native(NativeStorage.Owner(minimumCapacity: 2))
return
}
if _fastPath(guaranteedNative) {
nativeRemoveAll()
return
}
switch self {
case .Native:
nativeRemoveAll()
case .Cocoa(let cocoaStorage):
#if _runtime(_ObjC)
self = .Native(NativeStorage.Owner(minimumCapacity: cocoaStorage.count))
#else
_sanityCheckFailure("internal error: unexpected cocoa ${Self}")
#endif
}
}
Here you can see that the condition !keepCapacity
will be true, because removeAll()
is just removeAll(keepCapacity:)
with a default argument of false
. This code is from the storage enum, so it replaces itself with a new empty storage with a minimum capacity of 2.
Both statements do pretty much the same in theory, but I can imagine that in practice the initialisation can get optimised away, so that they do exactly the same.
things = [Thing]()
vs things.removeAll()
For array it's even easier to see here:
public init() {
_buffer = _Buffer()
}
See here:
public mutating func removeAll(keepCapacity keepCapacity: Bool = false) {
if !keepCapacity {
_buffer = _Buffer()
}
else {
self.replaceRange(self.indices, with: EmptyCollection())
}
}
As with the dictionary, _buffer
is the only property of Array
.
Same as for Dictionary
: Both statements do pretty much the same in theory, but I can imagine that in practice the initialisation can get optimised away, so that they do exactly the same.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With