为什么 Kotlin Sets 有索引?
Why do Kotlin Sets have indices?
我很好奇为什么 Kotlin Set
有索引。您可以使用 mySet.elementAt(index)
访问元素。我所知道的其他语言都没有此功能。如果集合不应该被排序但它们有索引,该功能是否有用?此外,此功能不会使 Kotlin 中的 Set
s 比其他语言中的其他 Set
s 慢吗?
Set
有 elementAt
方法,不是因为它是基于索引的(所以它不是“比其他语言慢”只是因为它有这个方法),而是因为它实现了 Iterable<T>
。 elementAt
是 Iterable<T>
上的扩展函数:
fun <T> Iterable<T>.elementAt(index: Int): T
Set
基于什么取决于您使用的 Set
的具体实现(Set
只是一个接口)。例如,HashSet
基于散列 table。
所以 Set
“免费”得到这个 elementAt
方法只是因为它实现了 Iterable<T>
。 not have elementAt
的唯一方法是不实现 Iterable<T>
,但这意味着你不能迭代 Set
。这不是很有用,是吗?另外,我稍后会谈到,elementAt
确实有它的用处。
因为 elementAt
是 Iterable<T>
上的扩展函数,它真正能做的就是要求迭代器给它 n 个元素,return 最后一个元素。就是这样 implemented.
public fun <T> Iterable<T>.elementAt(index: Int): T {
if (this is List)
return get(index)
return elementAtOrElse(index) { throw IndexOutOfBoundsException("Collection doesn't contain element at index $index.") }
}
...
public fun <T> Iterable<T>.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T {
if (this is List)
return this.getOrElse(index, defaultValue)
if (index < 0)
return defaultValue(index)
val iterator = iterator()
var count = 0
while (iterator.hasNext()) {
val element = iterator.next()
if (index == count++)
return element
}
return defaultValue(index)
}
如果你的 Set
没有特定的顺序(例如 HashSet
),那么它的迭代器将 return 元素也没有特定的顺序,所以使用 elementAt(x)
意义不大。另一方面,如果您使用的是有序集,例如 LinkedHashSet
(这是 setOf
和 mutableSetOf
创建的),那么使用 elementAt
确实有意义。
另请注意,elementAt
确实有 O(n) 时间,但这并不意味着使用集合的方法(例如 contains
)访问集合也有 O(n) 时间.这也取决于您使用的 Set
的具体实现。 LinkedHashSet.contains
和HashSet.contains
都是O(1)时间。
我很好奇为什么 Kotlin Set
有索引。您可以使用 mySet.elementAt(index)
访问元素。我所知道的其他语言都没有此功能。如果集合不应该被排序但它们有索引,该功能是否有用?此外,此功能不会使 Kotlin 中的 Set
s 比其他语言中的其他 Set
s 慢吗?
Set
有 elementAt
方法,不是因为它是基于索引的(所以它不是“比其他语言慢”只是因为它有这个方法),而是因为它实现了 Iterable<T>
。 elementAt
是 Iterable<T>
上的扩展函数:
fun <T> Iterable<T>.elementAt(index: Int): T
Set
基于什么取决于您使用的 Set
的具体实现(Set
只是一个接口)。例如,HashSet
基于散列 table。
所以 Set
“免费”得到这个 elementAt
方法只是因为它实现了 Iterable<T>
。 not have elementAt
的唯一方法是不实现 Iterable<T>
,但这意味着你不能迭代 Set
。这不是很有用,是吗?另外,我稍后会谈到,elementAt
确实有它的用处。
因为 elementAt
是 Iterable<T>
上的扩展函数,它真正能做的就是要求迭代器给它 n 个元素,return 最后一个元素。就是这样 implemented.
public fun <T> Iterable<T>.elementAt(index: Int): T {
if (this is List)
return get(index)
return elementAtOrElse(index) { throw IndexOutOfBoundsException("Collection doesn't contain element at index $index.") }
}
...
public fun <T> Iterable<T>.elementAtOrElse(index: Int, defaultValue: (Int) -> T): T {
if (this is List)
return this.getOrElse(index, defaultValue)
if (index < 0)
return defaultValue(index)
val iterator = iterator()
var count = 0
while (iterator.hasNext()) {
val element = iterator.next()
if (index == count++)
return element
}
return defaultValue(index)
}
如果你的 Set
没有特定的顺序(例如 HashSet
),那么它的迭代器将 return 元素也没有特定的顺序,所以使用 elementAt(x)
意义不大。另一方面,如果您使用的是有序集,例如 LinkedHashSet
(这是 setOf
和 mutableSetOf
创建的),那么使用 elementAt
确实有意义。
另请注意,elementAt
确实有 O(n) 时间,但这并不意味着使用集合的方法(例如 contains
)访问集合也有 O(n) 时间.这也取决于您使用的 Set
的具体实现。 LinkedHashSet.contains
和HashSet.contains
都是O(1)时间。