【问题标题】:Using a stream to iterate n times instead of using a for loop to create n items使用流迭代 n 次,而不是使用 for 循环创建 n 项
【发布时间】:2015-01-22 03:15:12
【问题描述】:

假设我想创建 n 个项目。在 Java 8 之前,我会写:

List<MyClass> list = new ArrayList<>();
for (int i = 0; i < n; i++) {
    list.add(new MyClass());
}

有没有一种优雅的方式来使用流创建 n 个项目?
我想到了这个:

List<MyClass> list = Stream.iterate(0, i -> i).limit(10)
    .map(o -> new MyClass()).collect(Collectors.toList());

是否有标准/更好的编码方式?

请注意,实际的用法有点复杂,使用流会更灵活,因为我可以在一行中立即通过其他函数泵送项目,甚至无需创建对列表的引用,例如对它们进行分组:

Stream.iterate(0, i -> i).limit(10).map(o -> new MyClass())
    .collect(Collectors.groupingBy(...));

【问题讨论】:

  • 您认为流将更具表现力/高效/有用?出于好奇?
  • 您可以使用IntStream#range(0, N)mapToObject

标签: loops java-8 java-stream


【解决方案1】:

您可以将Stream#generatelimit 一起使用:

Stream.generate(MyClass::new).limit(10);

【讨论】:

  • 为什么不Stream.iterate
  • @AsifMushtaq,因为每个项目的状态依赖于前一个。
【解决方案2】:

如果您事先知道 n,我认为使用其中一个流源来创建一个已知恰好具有 n 元素的流会更符合习惯。尽管有这些外观,但使用 limit(10) 并不一定会导致 SIZED 流恰好包含 10 个元素——它可能会更少。在并行执行的情况下,拥有SIZED 流可以改进拆分。

正如 Sotirios Delimanolis 在评论中指出的那样,您可以执行以下操作:

List<MyClass> list = IntStream.range(0, n)
    .mapToObj(i -> new MyClass())
    .collect(toList());

另一种选择是这样,虽然我不清楚它是否更好:

List<MyClass> list2 = Collections.nCopies(10, null).stream()
    .map(o -> new MyClass())
    .collect(toList());

你也可以这样做:

List<MyClass> list = Arrays.asList(new MyClass[10]);
list.replaceAll(o -> new MyClass());

但这会产生一个固定大小但可变的列表。

【讨论】:

    猜你喜欢
    • 2020-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多