如何在 Java 中生成连续整数的列表或数组?

2023-12-13

有没有一种简短而甜蜜的方法来生成List<Integer>,或者也许是一个Integer[] or int[],具有来自某些的连续值start值对end value?

That is, something shorter than, but equivalent to1 the following:

void List<Integer> makeSequence(int begin, int end) {
  List<Integer> ret = new ArrayList<>(end - begin + 1);
  for (int i=begin; i<=end; i++) {
    ret.add(i);
  }
  return ret;  
}

使用番石榴就很好。

Update:

绩效分析

由于这个问题已经收到了几个很好的答案,都使用本机 Java 8 和第三方库,所以我想我应该测试所有解决方案的性能。

第一个测试只是测试创建一个包含 10 个元素的列表[1..10]使用以下方法:

  • 经典数组列表:上面在我的问题中给出的代码(基本上与 adarshr 的答案相同)。
  • eclipse集合: 中给出的代码唐纳德的回答下面使用 Eclipse Collections 8.0。
  • 番石榴范围: 中给出的代码戴夫的回答以下。从技术上讲,这不会创建List<Integer>而是一个ContiguousSet<Integer>- 但既然它实现了Iterable<Integer>按顺序,它主要适合我的目的。
  • intStreamRange: 中给出的代码弗拉基米尔的回答下面,它使用IntStream.rangeClosed()- 这是在 Java 8 中引入的。
  • 流迭代: 中给出的代码卡塔林的回答下面也使用IntStreamJava 8 中引入的功能。

以下是对于上述所有大小为 10 的列表的结果(以每秒千次操作为单位)(数字越高越好):

List creation throughput

...对于大小为 10,000 的列表再次:

enter image description here

最后一张图表是正确的 - 除了 Eclipse 和 Guava 之外的解决方案都太慢,甚至无法获得单个像素条!快速解决方案是10,000到20,000times比其他人更快。

当然,这里发生的事情是,guava 和 eclipse 解决方案实际上并没有实现任何类型的 10,000 个元素列表 - 它们只是围绕起点和终点的固定大小的包装器。每个元素都是在迭代过程中根据需要创建的。由于我们实际上并未在此测试中进行迭代,因此成本被推迟。所有其他解决方案实际上都在内存中实现了完整列表,并在仅创建的基准测试中付出了沉重的代价。

让我们做一些更实际的事情,并迭代所有整数,对它们求和。所以在这种情况下IntStream.rangeClosed变体,基准看起来像:

@Benchmark
public int intStreamRange() {
    List<Integer> ret = IntStream.rangeClosed(begin, end).boxed().collect(Collectors.toList());  

    int total = 0;
    for (int i : ret) {
        total += i;
    }
    return total;  
}

在这里,图片发生了很大变化,尽管非实现解决方案仍然是最快的。这里的长度=10:

List<Integer> Iteration (length=10)

...且长度 = 10,000:

List<Integer> Iteration (length=10,000)

许多元素的长时间迭代使事情变得更加平衡,但即使在 10,000 个元素测试中,Eclipse 和 guava 的速度仍然是两倍以上。

所以如果你really want a List<Integer>, eclipse 集合似乎是最好的选择 - 但当然,如果您以更本机的方式使用流(例如,忘记.boxed()并在原始域中进行减少)您可能最终会比所有这些变体更快。


1 Perhaps with the exception of error handling, e.g., if end < begin, or if the size exceeds some implementation or JVM limits (e.g., arrays larger than 2^31-1.


对于 Java 8,它非常简单,甚至不再需要单独的方法:

List<Integer> range = IntStream.rangeClosed(start, end)
    .boxed().collect(Collectors.toList());

在 Java 16 或更高版本中:

List<Integer> range = IntStream.rangeClosed(start, end)
    .boxed().toList();
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在 Java 中生成连续整数的列表或数组? 的相关文章

随机推荐