Вопрос по append, list, scala, range, out-of-memory – Скала Range для Long

4

Я новичок в языке Scala.

Мне нужен диапазон для типа Long.

Мне нужен список [1, 2, 3 ... 10000000] с шагом 1. Если я использую до / до, я получаю ошибку из-за использования Long вместо Int.

Я пытаюсь написать простую функцию, которая ожидает начало, конец и пустой список и генерирует список [начало .. конец].

Вот моя функция:

<code>def range_l(start : Long, end : Long, list : List[Long]) : List[Long] = {
    if (start == end){
        val add_to_list = start :: list
        return add_to_list
    }
    else {
        val add_to_list = start :: list
        range_l(start + 1, end, add_to_list)
    }
}
</code>

Если я назову это как:range_l(1L, 1000000L, List()) я получилOutOfMemory ошибка в следующей строке:add_to_list = start :: list

Что вы можете посоветовать мне? Как я могу получитьRange[Long] или как я могу оптимизировать функцию. Как я могу избежать OutOfMemory?

Спасибо.

Диапазоны обычно не нуждаются в материализации. Пытаться1.to(Int.MaxValue) на REPL и посмотрите на результирующий тип. Не стесняйтесь тогдаlook at the Scala source для такого типа :) user166390
Зачем вам такой диапазон? Получить его довольно легко (см. Парадигматический ответ), но его использование часто нецелесообразно. Там могут быть лучшие решения вашей проблемы. Кроме того, в чем ваша ошибка?1 to 10000000 не выдает ошибку. Daniel C. Sobral
Вы говорите оRange, но ваша функция возвращаетList это разные виды в скале. Если ты хочешьList[Long], вы можетеList.range(0L, 10) 4e6

Ваш Ответ

3   ответа
7

Вы можете вместо этого использоватьNumericRange [Long] из стандартной библиотеки.

8

Вы можете создать такой диапазон, используя следующий синтаксис:

val range = 1L to 10000000L

«L» Обязательно сообщите компилятору, что литералы длинные, а не целые.

Вы можете использовать почти всеList методы в экземпляреrange, Это не должно заполнять вашу память, потому что промежуточные значения генерируются при необходимости. Диапазон может быть передан любому методу, ожидающемуTraversable[Long],Seq[Long],Iterable[Long], так далее.

Однако, если вам действительно нужноList просто позвониrange.toList (и увеличьте размер кучи для размещения всех элементов списка) ...

хотя1L to 10000000000L создает исключение IllegalArgumentException: & quot; seqs не может содержать больше, чем элементы Int.MaxValue & quot;
@DNA Да, действительно, в этом случае вы можете использовать потоки или свой собственный итератор. Стандартные коллекции lib имеют метод size, который должен возвращать Int ... Если у вас есть особые потребности, вы должны использовать специальную коллекцию.
6

Вам, вероятно, не нужен диапазон. Я бы взял Stream и перебрал его.

def stream(i: Long = 1): Stream[Long] = i #:: stream(i + 1)

создает бесконечный поток, где разница между элементами равна 1. Поскольку поток - это ленивая коллекция, вы не получите никаких ошибок. Чтобы перебрать более 10000000 элементов, вы просто используете следующее:

val range = stream take 10000000
for (i <- range) {
  ...
}

take 10000000 вернетStream с размером 10000000. Потому чтоStream являетсяIterable Вы можете передать его для понимания.

Похожие вопросы