在平常開發中,常常會遇到判斷一個Array
中元素個數是否爲0。通常來講,有兩種方法,一種是isEmpty
,一種是array.count == 0
。那哪種方法更好呢?在蘋果的官方文檔中,isEmpty
方法上有這樣一段註釋git
/// When you need to check whether your collection is empty, use the `isEmpty` property instead of checking that the `count` property equal to zero.
/// For collections that dont conform `RandomAccessCollection`, accessing the `count` property iterates through the elements of the collection.
- Complexity: O(1)
複製代碼
大體意思就是,當判斷你的集合是否爲空時,推薦使用isEmpty
屬性來代替判斷count
屬性是否等於0。由於集合類型的count
屬性會遍歷集合裏的全部元素。isEmpty
屬性的時間複雜度爲O(1)。 接下來咱們就從源代碼角度來分析一下這2者的區別吧。如下的代碼位於github
的stdlib/public/core/Collection.swift
文件裏。github
public protocol Collection: Sequence {
var isEmpty: Bool { get }
var count: Int { get }
var startIndex: Index { get }
var endIndex: Index { get }
}
複製代碼
首先,isEmpty
和count
都是Collection
協議的計算型屬性。其次,都有一個默認實現。swift
extension Collection {
public var isEmpty: Bool {
return startIndex == endIndex
}
}
複製代碼
isEmpty
方法的實現很簡單,判斷startIndex
和endIndex
是否相等就能夠了。那startIndex
和endIndex
又是2個計算型屬性,那麼這2個的實現又是怎麼樣的呢?在這個文件裏咱們沒有找到默認實現,因此咱們就前往同層文件夾的Array.swift
文件裏去查看一下了。 startIndex
的實現很簡單,直接返回了一個0
bash
public var startIndex: Int {
return 0
}
複製代碼
endIndex
的相對就稍微複雜一點了dom
@inlinable
public var endIndex: Int {
@inlinable
get {
return _getCount()
}
}
internal func _getCount() -> Int {
return _buffer.count
}
複製代碼
看到這兒,裏面的再看下去就太深了(我也看不明白了),姑且看成_buffer
是Array
類型的內部實現吧。ui
public var count: Int {
return distance(from: startIndex, to: endIndex)
}
public func distance(from start: Index, to end: Index) -> Int {
_precondition(start <= end,
"Only BidirectionalCollections can have end come before start")
var start = start
var count = 0
while start != end {
count = count + 1
formIndex(after: &start)
}
return count
}
複製代碼
count
方法內部調用了一個distance(from:to:)
的方法,並且在distance
內部有一個while
循環遍歷直到start==end
,那麼count
的事件複雜度就是o(n)
。spa
所以2個屬性相比,在使用的時候,最好仍是使用isEmpty
屬性判斷Array
元素是否爲空。code