生成[1..10],或者可能是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]的列表:
classicArrayList:上面在我的问题中给出的代码(和adarshr的答案基本相同)。
eclipseCollections:下面使用Eclipse Collections 8.0在Donald的回答中给出的代码。
guavaRange:daveb在下面的答案中给出的代码。 从技术上讲,这不会创建一个end,而是一个begin - 但由于它按顺序实现了2^31-1,它主要用于我的目的。
intStreamRange:下面的Vladimir的答案中给出的代码,它使用了end - 这是在Java 8中引入的。
streamIterate:下面的Catalin答案中给出的代码,它也使用了Java 8中引入的end功能。
以下是每秒千位操作的结果(更高的数字更好),对于以上所有的大小为10的列表:
......再次列出10,000的清单:
最后一张图是正确的 - Eclipse和Guava以外的解决方案太慢,甚至无法获得单个像素条! 快速解决方案比其他解决方案快10,000到20,000倍。
当然,这里发生的是guava和eclipse解决方案实际上并没有实现任何类型的10,000元素列表 - 它们只是起始点和端点周围的固定大小的包装器。 在迭代期间根据需要创建每个元素。 由于我们实际上没有在此测试中进行迭代,因此延迟了成本。 所有其他解决方案实际上实现了内存中的完整列表,并且在仅创建基准测试中付出了沉重的代价。
让我们做一些更现实的事情,并迭代所有整数,总结它们。 因此,对于end变体,基准测试如下:
@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:
对许多元素进行的长时间迭代使得事情变得非常均衡,但即使在10,000元素测试中,日食和番石榴的速度仍然快了两倍多。
因此,如果你真的想要一个end,eclipse集合似乎是最好的选择 - 当然如果你以更本地的方式使用流(例如,忘记begin并在原始域中进行缩减),你可能最终会比 所有这些变种。
1也许除了错误处理之外,例如,如果end