必须有一种简短而甜美的方式来生成具有从某个起始值到结束值的顺序值的List< Integer>,或者可能是Integer []或int []。
也就是说,短于但等于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]的列表:
> classicArrayList:上面给出的代码在我的问题(和本质上相同的adarshr的答案)。
> eclipseCollections:下面的代码在Donald’s answer中给出,使用Eclipse Collections 8.0。
> guavaRange:下面的代码。在技术上,这不创建List< Integer>而是ContiguousSet< Integer> – 但是由于它实现了Iterable< Integer>按顺序,它大多是为我的目的工作。
> intStreamRange:在下面的Vladimir’s answer中给出的代码,它使用在Java 8中引入的IntStream.rangeClosed()。
> streamIterate:在下面的Catalin’s answer中给出的代码,它也使用了Java 8中引入的IntStream功能。
这里是结果以公斤操作每秒(更高的数字更好),对于所有以上列表的大小10:
…并再次列出大小为10,000的列表:
最后的图表是正确的 – 除了Eclipse和Guava之外的解决方案太慢,甚至得不到一个像素吧!快速解决方案比其他解决方案快10,000到20,000倍。
这里发生的事情,当然是,番石榴和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:
… and length = 10,000:
对许多元素的长期迭代使事情变得很多,但是即使在10,000元素测试中,eclipse和番石榴仍然是两倍以上。
因此,如果你真的想要一个List< Integer>,eclipse集合看起来是最好的选择 - 但是如果你使用更本地的方式(例如,忘记.boxed()和做一个简化的原始域)可能会比所有这些变体结束得更快。 1也许除了错误处理之外,例如,开始,或者如果大小超过一些实现或JVM限制(例如,大于2 ^ 31-1的数组)。