有没有一种方法可以在Kotlin中使用初始化函数构造一个HashSet?
要从Facebook Hacker Cup 2016 Boomerang Constelations问题的文件中读取星星,可以定义以下扩展函数:
fun BufferedReader.readStars(n: Int): Set<Star> { return Array(n) { val (l1, l2) = readLine().split(" ").map { it.toInt() } Star(l1, l2) }.toHashSet() }
代码是紧凑的,但值首先读入一个数组,然后转换为HashSet
。 有没有一种方法可以直接初始化Kotlin中的大小为n
和初始化函数的HashSet
?
更新:标准Kotlin库中是否存在一种方法?
您始终可以使用apply
来就地初始化对象:
HashSet<Star>(n).apply { repeat(n) { val (l1, l2) = readLine()!!.split(' ').map { it.toInt() } put(Star(l1, l2)) } }
如果每次输入太麻烦,写一个扩展函数:
inline fun <T> createHashSet(n : Int, crossinline fn: (Int) -> T) = HashSet<T>(n).apply { repeat(n) { add(fn(it)) } }
用法:
createHashSet<Star>(n) { val (l1, l2) = readLine()!!.split(' ').map { it.toInt() } Star(l1, l2) }
由于HashSet
是一个Java类,因此您只能以JDK提供的方式对其进行初始化。
虽然在Kotlin运行时没有帮助方法,但自己编写它很容易:
public fun <T> hashSetOf(size: Int, initializer: (Int) -> T): HashSet<T> { val result = HashSet<T>(size) 0.rangeTo(size - 1).forEach { result.add(initializer(it)) } return result }
正如@miensol指出的那样, HashSet
初始化仅限于JDK提供的构造函数。 Kotlin添加了一个hashSetOf
函数,它初始化一个空的HashSet
,然后将指定的元素添加到它。
为了避免首先将值读入数组,可以使用kotlin.Sequence
谁的“价值评估懒惰”:
fun BufferedReader.readStars(n: Int): Set<Star> { return lineSequence().take(n).map { val (l1, l2) = it.split(" ").map { it.toInt() } Star(l1, l2) }.toHashSet() }
这似乎是你问一个XY问题( http://xyproblem.info/ )。 你真的想知道如何以最有效的方式编写readStars
,而是询问HashSet
。 我想@mfulton26也会根据提问的内容来回答你的问题。
这里是“如何以最有效的方式写这个”的答案。
你有两个选择。 首先,一个在最后自动关闭流的版本:
fun BufferedReader.readStars(n: Int): Set<Star> { return use { lineSequence().map { line -> val idx = line.indexOf(' ') Star(line.substring(0, idx).toInt(), line.substring(idx + 1).toInt()) }.toSet() } }
其次,一个版本不会:
fun BufferedReader.readStars(n: Int): Set<Star> { return lineSequence().map { line -> val idx = line.indexOf(' ') Star(line.substring(0, idx).toInt(), line.substring(idx+1).toInt()) }.toSet() }
这两个版本都不会创建数组,也不会创建数据副本。 他们通过创建Set并直接填充的序列来传输数据。
其他说明
如果您真的关心分配和性能,则无需使用拆分。 只需使用indexOf(char)
并使用substring
字符串自己拆分substring
。
如果你做了一个分割,那么当你想要分割一个char
时,请使用split(char)
而不是split(String)