有没有产生一个简短而亲切的方式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和第三方库都可以很好地回答这个问题,所以我认为我将测试所有解决方案的性能。
第一个测试只是[1..10]使用以下方法测试创建包含10个元素的列表:
classicArrayList:我问题中上面给出的代码(与adarshr的回答基本相同)。 eclipseCollections:下面的Donald答案中使用Eclipse Collections 8.0 给出的代码。 guavaRange:下面的daveb答案中给出的代码。从技术上讲,这并不会创建List 而是ContiguousSet -,但是由于它Iterable 是按顺序实现的,因此大多数情况下可以实现我的目的。 intStreamRange:下面弗拉基米尔的答案中给出的代码,它使用IntStream.rangeClosed()-在Java 8中引入的。 streamIterate:下面的Catalin答案中给出的代码,它也使用IntStreamJava 8中引入的功能。 以下是上述所有大小为10的列表的结果,以千公斤/秒为单位(数字越大越好):
列表创建吞吐量
...再一次列出大小为10,000的列表:
在此处输入图片说明
最后一张图表是正确的-除Eclipse和Guava之外的解决方案太慢,甚至无法获得单个像素条!快速的解决方案是其他解决方案的10,000到20,000 倍。
当然,这里发生的是番石榴和日食解决方案实际上并没有实现任何类型的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:
List <整数>迭代(长度= 10)
...且长度= 10,000:
List <整数>迭代(长度= 10,000)
对许多元素的长时间迭代使事情变得平淡无奇,但是即使在10,000个元素测试中,日食和番石榴的速度仍是其两倍以上。
因此,如果您确实想要List ,eclipse集合似乎是最好的选择-但是,当然,如果您以更原生的方式使用流(例如,忘记.boxed()并进行原始域的缩减),则最终结果可能会比所有这些都更快变体。
1也许是错误处理的例外,例如,如果end< begin,或者大小超出某些实现或JVM限制(例如,大于的数组)2^31-1。 问题来源于stack overflow
使用Java 8,它是如此简单,因此它甚至不再需要单独的方法:
List range = IntStream.rangeClosed(start, end) .boxed().collect(Collectors.toList());
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。