¿Hay alguna manera de build un HashSet con function de initialization en Kotlin?

Para leer las estrellas de un file en el problema de constelaciones Boomerang 2016 de Facebook Hacker Cup , se puede definir la siguiente function de extensión:

fun BuffenetworkingReader.readStars(n: Int): Set<Star> { return Array(n) { val (l1, l2) = readLine().split(" ").map { it.toInt() } Star(l1, l2) }.toHashSet() } 

El código es compacto, pero los valores se leen primero en una matriz y luego se convierten en un HashSet . ¿Hay alguna manera de inicializar directamente un HashSet con el tamaño de n y la function de initialization en Kotlin?

ACTUALIZACIÓN: ¿Hay una forma existente en las librerías estándar de Kotlin?

Siempre puede usar apply para inicializar objects en el lugar:

 HashSet<Star>(n).apply { repeat(n) { val (l1, l2) = readLine()!!.split(' ').map { it.toInt() } put(Star(l1, l2)) } } 

Si eso también es demasiado inconveniente, escriba cada vez, escriba una function de extensión:

 inline fun <T> createHashSet(n : Int, crossinline fn: (Int) -> T) = HashSet<T>(n).apply { repeat(n) { add(fn(it)) } } 

Uso:

 createHashSet<Star>(n) { val (l1, l2) = readLine()!!.split(' ').map { it.toInt() } Star(l1, l2) } 

Debido a que HashSet es una class Java, solo puede inicializarlo de la forma indicada por JDK.

Si bien no hay un método de ayuda en el time de ejecución de Kotlin , es fácil escribirlo usted mismo así:

 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 } 

Como @miensol ha señalado, la initialization de HashSet está limitada a los constructores puestos a disposition por el JDK. Kotlin ha agregado una function hashSetOf que inicializa un HashSet vacío y luego le agrega los elementos especificados.

Para evitar la primera lectura de los valores en una matriz, puede usar un kotlin.Sequence los "valores evaluados perezosamente":

 fun BuffenetworkingReader.readStars(n: Int): Set<Star> { return lineSequence().take(n).map { val (l1, l2) = it.split(" ").map { it.toInt() } Star(l1, l2) }.toHashSet() } 

Parece que estás haciendo una pregunta XY ( http://xyproblem.info/ ). Realmente desea saber cómo escribir readStars de la manera más eficiente, pero en su lugar pregunta acerca de HashSet . Creo que @ mfulton26 también responde su pregunta dependiendo de lo que se le pregunte.

Aquí está la respuesta para "cómo escribo esto de la manera más eficiente":

Tienes dos opciones. Primero, una versión que cierra automáticamente la secuencia al final:

 fun BuffenetworkingReader.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() } } 

Y segundo, una versión que no:

 fun BuffenetworkingReader.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() } 

Ninguna versión crea una matriz, ni hacen copys de datos. Transmiten los datos a través de una secuencia que crea el set y lo llena directamente.

Otras notas

No es necesario utilizar split si realmente está preocupado por las asignaciones y el performance. Solo use indexOf(char) y divida la cadena usted mismo usando substring .

Si haces una split, entonces usa split(char) not split(String) cuando estás buscando dividir en un char

  • Kotlin no puede crear el campo @Autowinetworking en Class anotado con @Configuration @EnableWebMvc
  • Android 2 Retrofit llamada sincrónica
  • Kotlin: cómo get el valor del atributo de anotación
  • La class Kotlin Custom View implementa una interfaz que no se puede resolver en `: app: compileDebugKotlinAfterJava`. La versión idéntica de Java funciona bien
  • La variable 'ejecutable' debe ser inicializada
  • Las classs de Kotlin que contienen android-extensiones no se basan en construcciones consecuentes
  • Invocando Acción por reference en Kotlin
  • properties basadas en el map de kotlin y Jackson no funcionan: delegue puntos en un map diferente que la propiedad del map
  • ¿Cómo get un KClin KClass de una cadena de nombre de class de package?
  • Kotlin: ¿Qué hacen los operadores más / less unarios con los numbers?
  • IntelliJ importa Java Boolean y luego arroja un error