为什么 Kotlin Sets 有索引?

Dj *_*shi 2 set kotlin

我很好奇为什么 KotlinSet有索引。您可以使用 来访问元素mySet.elementAt(index)。我所知道的其他语言都没有这个功能。如果集合不应该排序但它们有索引,那么该功能是否有用?另外,这个特性难道不会使得SetKotlin 中的 s 比Set其他语言中的其他 s 慢吗?

Swe*_*per 7

Set具有该elementAt方法,不是因为它基于索引(因此它不会仅仅因为它具有该方法而“比其他语言慢”),而是因为它实现了Iterable<T>. elementAt是 的扩展函数Iterable<T>

fun <T> Iterable<T>.elementAt(index: Int): T
Run Code Online (Sandbox Code Playgroud)

aSet基于什么取决于Set您使用的具体实现(Set只是一个接口)。HashSet例如,基于哈希表。

因此,“免费”Set获得这个方法只是因为它实现了. 具有的唯一方法是不实现,但这意味着您无法迭代. 这不是很有用,是吗?而且,正如我稍后将讨论的,确实有它的用途。elementAtIterable<T>elementAtIterable<T>SetelementAt

由于elementAt是 的扩展函数Iterable<T>,它真正能做的就是要求迭代器给它 n 个元素,并返回最后一个元素。这就是它的实现方式。

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)
}
Run Code Online (Sandbox Code Playgroud)

如果你的Set没有特定的顺序(例如HashSet),那么它的迭代器也将返回没有特定顺序的元素,所以使用elementAt(x)不是很有意义。另一方面,如果您使用的是有序集,例如LinkedHashSet(这就是setOfandmutableSetOf创建的),那么使用elementAt确实有意义。

另请注意,elementAt确实有 O(n) 时间,但这并不意味着使用集合的方法(例如contains)访问集合也有 O(n) 时间。这还取决于Set您使用哪种具体实现。和LinkedHashSet.contains都是HashSet.containsO(1) 时间。