Есть ли короткий и приятный способ сгенерировать List
или, возможно, Integer[]
или int[]
с последовательными значениями от некоторого значения start
до end
значение?
То есть что-то короче, но эквивалентно 1 следующему:
void List makeSequence(int begin, int end) {
List ret = new ArrayList<>(end - begin + 1);
for (int i=begin; i<=end; i++) {
ret.add(i);
}
return ret;
}
Использование гуавы прекрасно.
Обновление:
Поскольку на этот вопрос было получено несколько хороших ответов, как с использованием собственных библиотек Java 8, так и сторонних библиотек, я решил проверить производительность всех решений.
Первый тест просто проверяет создание списка из 10 элементов [1..10]
с использованием следующих методов:
List
, а скорее ContiguousSet
-, но поскольку он реализует Iterable
в порядке -, он в основном работает для моих целей.IntStream.rangeClosed()
-, представленный в Java 8.IntStream
функциональные возможности, представленные в Java 8.Вот результаты в кило -операций в секунду (более высокие числа лучше ), для всего вышеперечисленного со списками размером 10:
... и снова для списков размером 10 000:
Последняя диаграмма верна -решения, отличные от Eclipse и Guava, слишком медленны, чтобы получить даже полоску с одним пикселем!Быстрые решения в 10 000–20 000 раз быстрее, чем остальные.
Конечно, здесь происходит то, что решения guava и eclipse на самом деле не материализуют какой-либо список из 10 000 элементов -, а просто обертки фиксированного -размера вокруг начальной и конечной точек. Каждый элемент создается по мере необходимости во время итерации. Поскольку мы на самом деле не повторяем этот тест, стоимость отложена. Все остальные решения фактически материализуют полный список в памяти и платят высокую цену только созданием -эталонного теста.
Давайте сделаем что-нибудь более реалистичное, а также переберем все целые числа, просуммировав их. Так что в случае с вариантом IntStream.rangeClosed
бенчмарк выглядит как:
@Benchmark
public int intStreamRange() {
List ret = IntStream.rangeClosed(begin, end).boxed().collect(Collectors.toList());
int total = 0;
for (int i : ret) {
total += i;
}
return total;
}
Здесь картинки сильно меняются, хотя решения без материализации -по-прежнему самые быстрые. Здесь длина = 10:
... и длина = 10 000:
Долгая итерация по многим элементам во многом выравнивает ситуацию, но eclipse и guava остаются более чем в два раза быстрее даже в тесте на 10 000 элементов.
Итак, если вы действительно хотите List
, коллекции eclipse кажутся лучшим выбором -, но, конечно, если вы используете потоки более естественным образом (, например, забывая .boxed()
и, выполняя сокращение примитивного домена ), вы, вероятно, окажетесь быстрее, чем все эти варианты.
1 Возможно, за исключением обработки ошибок, например, если end
begin, или если размер превышает некоторые ограничения реализации или JVM (, например, массивы больше, чем 2^31-1
.