Bee*_*ope 105 java arrays collections apache-commons guava
是否有一种简短而甜蜜的方式来生成一个List<Integer>
或者一个 Integer[]
或者int[]
从某个start
值到end
值的连续值?
也就是说,短于,但相当于以下1:
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;
}
Run Code Online (Sandbox Code Playgroud)
番石榴的使用很好.
更新:
由于这个问题已经收到了几个很好的答案,无论是使用本机Java 8还是第三方库,我都认为我会测试所有解决方案的性能.
第一个测试只是[1..10]
使用以下方法测试创建10个元素的列表:
List<Integer>
而是创造一个ContiguousSet<Integer>
- 但由于它Iterable<Integer>
按顺序实现,它主要用于我的目的.IntStream.rangeClosed()
- 这是在Java 8中引入的.IntStream
了Java 8中引入的功能.以下是每秒千位操作的结果(更高的数字更好),对于以上所有的大小为10的列表:
......再次列出10,000的清单:
最后一张图是正确的 - Eclipse和Guava以外的解决方案太慢,甚至无法获得单个像素条!快速解决方案比其他解决方案快10,000到20,000 倍.
当然,这里发生的是,番石榴和日食解决方案实际上并没有实现任何类型的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;
}
Run Code Online (Sandbox Code Playgroud)
虽然非物化解决方案仍然是最快的,但图片变化很大.这里的长度= 10:
......和长度= 10,000:
对许多元素进行的长时间迭代使得事情变得非常均衡,但即使在10,000元素测试中,日食和番石榴的速度仍然快了两倍多.
因此,如果你真的想要一个List<Integer>
,eclipse集合似乎是最好的选择 - 当然如果你以更原生的方式使用流(例如,忘记.boxed()
并减少原始域)你可能会比所有这些更快变种.
1也许除了错误处理之外,例如,如果end
< begin
,或者大小超过某些实现或JVM限制(例如,大于2^31-1
.
Vla*_*eev 163
使用Java 8它非常简单,因此它甚至不再需要单独的方法:
List<Integer> range = IntStream.rangeClosed(start, end)
.boxed().collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
dav*_*veb 26
嗯,这个班轮可能符合条件(使用番石榴山脉)
ContiguousSet<Integer> integerList = ContiguousSet.create(Range.closedOpen(0, 10), DiscreteDomain.integers());
System.out.println(integerList);
Run Code Online (Sandbox Code Playgroud)
这不会创建List<Integer>
,但ContiguousSet
提供相同的功能,特别是实现Iterable<Integer>
允许foreach
以相同的方式实现List<Integer>
.
在旧版本(Guava 14之前的某个地方),你可以使用它:
ImmutableList<Integer> integerList = Ranges.closedOpen(0, 10).asSet(DiscreteDomains.integers()).asList();
System.out.println(integerList);
Run Code Online (Sandbox Code Playgroud)
两者都产生:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
小智 9
以下单行Java 8版本将生成[1,2,3 ... 10].第一个arg iterate
是序列中的第一个nr,第一个arg limit
是最后一个数字.
List<Integer> numbers = Stream.iterate(1, n -> n + 1)
.limit(10)
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
这是我使用Core Java最短的时间.
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;
}
Run Code Online (Sandbox Code Playgroud)
您可以使用Eclipse Collections中的Interval
类。
List<Integer> range = Interval.oneTo(10);
range.forEach(System.out::print); // prints 12345678910
Run Code Online (Sandbox Code Playgroud)
该Interval
班是懒惰的,所以不存储所有的值。
LazyIterable<Integer> range = Interval.oneTo(10);
System.out.println(range.makeString(",")); // prints 1,2,3,4,5,6,7,8,9,10
Run Code Online (Sandbox Code Playgroud)
您的方法将可以按以下方式实现:
public List<Integer> makeSequence(int begin, int end) {
return Interval.fromTo(begin, end);
}
Run Code Online (Sandbox Code Playgroud)
如果您希望避免将整数作为Integers装箱,但仍希望使用列表结构,则可以使用Eclipse Collections中的IntList
with IntInterval
。
public IntList makeSequence(int begin, int end) {
return IntInterval.fromTo(begin, end);
}
Run Code Online (Sandbox Code Playgroud)
IntList
有方法sum()
,min()
,minIfEmpty()
,max()
,maxIfEmpty()
,average()
和median()
可用的接口。
为清楚起见更新:2017年11月27日
An Interval
是一个List<Integer>
,但是它是惰性的并且是不变的。这对于生成测试数据非常有用,尤其是在您处理大量集合时。如果你愿意,你可以在一个时间间隔轻松复制到List
,Set
或Bag
如下:
Interval integers = Interval.oneTo(10);
Set<Integer> set = integers.toSet();
List<Integer> list = integers.toList();
Bag<Integer> bag = integers.toBag();
Run Code Online (Sandbox Code Playgroud)
An IntInterval
是ImmutableIntList
延伸的IntList
。它还具有转换器方法。
IntInterval ints = IntInterval.oneTo(10);
IntSet set = ints.toSet();
IntList list = ints.toList();
IntBag bag = ints.toBag();
Run Code Online (Sandbox Code Playgroud)
An Interval
和an IntInterval
没有相同的equals
合同。
现在,您可以从原始流创建原始集合。有withAll
和ofAll
方法取决于您的喜好。如果您很好奇,请解释为什么我们都在这里。这些方法适用于可变且不变的Int / Long / Double列表,集合,袋子和堆栈。
Assert.assertEquals(
IntInterval.oneTo(10),
IntLists.mutable.withAll(IntStream.rangeClosed(1, 10)));
Assert.assertEquals(
IntInterval.oneTo(10),
IntLists.immutable.withAll(IntStream.rangeClosed(1, 10)));
Run Code Online (Sandbox Code Playgroud)
注意:我是Eclipse Collections的提交者
归档时间: |
|
查看次数: |
80228 次 |
最近记录: |