【问题标题】:How can I create a list with N objects?如何创建包含 N 个对象的列表?
【发布时间】:2017-07-24 08:14:28
【问题描述】:

我正在尝试创建一个包含 n 个元素的对象列表。我正在尝试以尽可能多的 java 8 方式执行此操作。类似于此处要求 c# 的问题: Creating N objects and adding them to a list

类似这样的:

List <Objects> getList(int numOfElements)
{

}

【问题讨论】:

  • 你能贴出你试过的代码吗?
  • 你到底想达到什么目的?
  • 您是否真的要在问题发布后的 2 分钟内关闭问题?
  • @Guy 它在 C# 中:D

标签: java list collections java-8


【解决方案1】:

如果我没看错:

List <Object> getList(int numOfElements){
     return IntStream.range(0, numOfElements)
              .mapToObj(Object::new) // or x -> new Object(x).. or any other constructor 
              .collect(Collectors.toList()); 
}

如果你想要同一个对象 n 次:

Collections.nCopies(n, T)

【讨论】:

  • 我发现我没有弥补它......弥补它。 :)
  • Collections.nCopies(n, T) 将返回一个不可变的List&lt;T&gt; 如果您需要获得一个可编辑的List&lt;T&gt;,您应该创建一个空列表,然后调用 addAll 传递 nCopies List&lt;T&gt; temp = new ArrayList&lt;&gt;(); temp.addAll(Collections.nCopies(n, T)); return temp; 的结果
  • @afj88 答案的简短版本:return new ArrayList&lt;&gt;(Collections.nCopies(n, T));
【解决方案2】:

您可以将Stream.generate(Supplier&lt;T&gt;) 与对构造函数的引用结合使用,然后使用Stream.limit(long) 指定您应该构造多少个:

Stream.generate(Objects::new).limit(numOfElements).collect(Collectors.toList());    

至少对我来说,这比使用IntStream 进行迭代更易读,更清楚地说明意图,例如Alberto Trindade Tavares suggested.

如果您想要在复杂性和内存使用方面表现更好的东西,请将结果大小传递给Stream.collect(Collector&lt;? super T,A,R&gt;):

Stream.generate(Objects::new).limit(numOfElements).collect(Collectors.toCollection(() -> new ArrayList<>(numOfElements)));

【讨论】:

  • 虽然正确,但请注意,这将比IntStream 方法更糟糕地并行化——因为这仍然是一个无限流(限制不会引入SIZED 属性);否则向我 +1。
  • @Eugene:如果你想要最大的并行性能,你应该使用Arrays.asList(IntStream.range(0, numOfElements) .mapToObj(Objects::new) .toArray(Objects[]::new));
  • @Holger 我认为这与拆分器下方有关?而ArraySpliterator 会比RangeIntSpliterator 更好?
  • @Eugene:不,在这两种情况下你都有相同的拆分器,因为源仍然是一个范围。但是toArray 带有(子)大小的流将立即分配最终数组并让每个线程写入该数组的正确部分,而collect(Collectors.toList()) 则收集到本地列表并需要额外的合并步骤。此外,toList() 使用的列表可能需要(多次)容量增加操作。另请参阅this comment
  • 我会说我们可以通过调用它的构造函数来自定义我们的对象,即Stream.generate(() -&gt; new SomeClassName(someValue_01, ... , someValue_N)) .limit(size) .collect(Collectors.toList());或者甚至我们可以通过自定义supplier来生成
【解决方案3】:

您在 Java 8 中使用streams 提到的 C# 代码的等效实现如下(编辑使用 mapToObj,由 @Eugene 建议):

List <Objects> getList(int numOfElements)
{
  return IntStream.range(0, numOfElements)
                  .mapToObj(x -> new Objects())
                  .collect(Collectors.toList()); 
}

【讨论】:

  • 有点乱。此处应使用的地图。
  • 我也不太确定,但我认为他想向他正在创建的对象构造函数发送一些参数 - 至少是 x,所以看起来应该是 .map(x -&gt; new Objects(x))或更好.map(Objects::new)
  • OP 没有说清楚。如果他想使用 x 作为构造函数的参数,那么您的答案是最好的答案(已赞成)
【解决方案4】:

为什么不保持简单呢?如果您想使用 LINQ 或 Lambda,它绝对是可能的,但问题是它是否更具可读性或可维护性。

List <Objects> getList(int numOfElements)
{
  List<Objects> objectList = new LinkedList<>();
  for(int i = 0; i <= numOfElements; i++)
  {
    objectList.add(new Object());
  }
  return objectList;
}

如果你坚持这可以是 lambda:

  return IntStream.range(0, numOfElements)
                  .mapToObj(x -> new Objects())
                  .collect(Collectors.toList()); 

感谢@Alberto Trindade,因为他发布的速度比我快。

【讨论】:

  • 感谢您的回复。我自己更喜欢更老派的方法。但是使用 Java8ified 解决方案是一个要求 :(
【解决方案5】:

如果您不介意第三方依赖,以下内容将适用于 Eclipse Collections:

List<Object> objects = Lists.mutable.withNValues(10, Object::new);
Verify.assertSize(10, objects);

注意:我是 Eclipse Collections 的提交者。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-24
    • 1970-01-01
    相关资源
    最近更新 更多