Создание класса, который создает массив Int с элементами между двумя аргументами (intStart, intEnd)

avatar
Lahty
8 августа 2021 в 19:46
41
2
0

Привет всем и спасибо за ваше время! У меня есть проблема. Короче говоря, я хочу создать класс, экземпляр которого хранит данные между двумя аргументами этого класса. Подобно классу "IntRange". Например: val r1 = IntRange(0,5) // вывод 0 1 2 3 4 5. Пытался объяснить как можно больше, английский язык не язык болтовни :) Что я пробовал:

fun main(args: Array<String>) {
    val ownArray = OwnIntRange(0,2).getNumbers()
    
}

public interface Counter{
    fun getNumbers(): Array<Int>
    var counter: Int
}

class OwnIntRange(val intMin: Int, val intMax: Int): Counter{
    override var counter = 0
    override fun getNumbers(): Array<Int> {

        for (number in intMin..intMax){
            getNumbers()[counter] = number
            counter++
        }
        return getNumbers()
    }
}

//result: StackOverflowError

если бы вы могли исправить мой подход, я был бы очень счастлив. Любая критика приветствуется!

Источник

Ответы (2)

avatar
gidds
8 августа 2021 в 22:35
0

Проблема в том, что ваша функция getNumbers() всегда вызывает себя хотя бы один раз. Который называет себя. Который называет себя. Который вызывает сам себя…  Таким образом, он застревает в бесконечной серии вложенных вызовов, и для их хранения не хватает места в стеке.

Рекурсия может быть допустимым методом, но вам всегда нужно условие завершения, точка, после которой она перестаёт возвращать — которая your начинает вызывать сама себя кода не имеет. Однако в этом случае рекурсия вообще не нужна.

Я не могу полностью понять ваши намерения в этой реализации, но вот немного другая, которая работает:

override fun getNumbers(): Array<Int> {
    val a = Array<Int>(intMax - intMin + 1){ 0 }

    for (number in intMin..intMax)
        a[number - intMin] = number

    return a
}

(Обратите внимание, что здесь не используется counter; похоже, что он вообще не нужен.)

То, что можно было бы написать намного проще (и немного эффективнее), лучше используя параметр init в конструкторе Array:

override fun getNumbers() = Array(intMax - intMin + 1){
    it + intMin
}

Также не принято (и возможно плохо) включать тип в имена ваших переменных; просто вызывая их, например. min и max было бы проще и легче читать. (Также не потребуется переименование, если вы измените тип с Int на Long или что-то еще.)

Конечно, в рабочем коде вам, вероятно, вообще не понадобится этот класс, так как IntRange подойдет. Если вам нужен свой собственный класс, я бы очень серьезно посмотрел на то, действительно ли нужен метод getNumbers(), поскольку почти наверняка были бы лучшие подходы, которые не создавали бы временные массивы, например с помощью шаблона посетителя.

Lahty
12 августа 2021 в 07:13
0

Теперь я понимаю! Большое спасибо. Ваш ответ удивителен и охватывает все мои проблемы.

avatar
JarekIT
8 августа 2021 в 20:00
0

Ява 8

override fun getNumbers(intMin: Int, intMax: Int): IntArray {
    return IntStream.rangeClosed(intMin,intMax).toArray()
}

или

override fun getNumbers(intMin: Int, intMax: Int): List<Int> {
        return IntStream.rangeClosed(intMin,intMax).toList()
    }

rangeClosed -> Возвращает последовательный упорядоченный IntStream от startInclusive (включительно) до endInclusive (включительно) с шагом приращения 1.

public static IntStream rangeClosed(int startInclusive, int endInclusive)
Lahty
12 августа 2021 в 07:17
0

Ага, это тоже работает. Спасибо за Ваш ответ!