【问题标题】:Java 8 - what is the correct way to fill an arraylist with the same object using Stream API?Java 8 - 使用 Stream API 用相同的对象填充数组列表的正确方法是什么?
【发布时间】:2017-03-08 13:53:17
【问题描述】:

我是 Stream API 的新手,我正在寻找更优雅和最短的方法来使用与此代码等效的 Stream API用相同的对象填充 ArrayList:

SomeObject someObject = new SomeObject();
List<SomeObject> someObjectList = new ArrayList<>();

int maxLimitValue = 70; //for example
for(int i=0; i<=maxLimitValue; i++){
   someObjectList.add(someObject);
}

我已经为当前的任务看到了许多不同的解决方案:

This variant 几乎是我想要的,但是对象是自动生成的,但我需要使用创建一次的同一个对象。

This solution也差不多是我需要的了,但是我不确定这个对象的拷贝和返回的List类型不是 ArrayList(它返回的是CopiesList类型,不能添加到ArrayList 在以后的操作中)。

附言也许它可能是重复的,但我真的找不到使用 Stream API 的正确且简短的方法。

更新(assylias 添加):

是的,我同意你对这个变体的看法:

List<SomeObject> list = Collections.nCopies(70, someObject);

但是,当我打开这个方法时:

public static <T> List<T> nCopies(int n, T o) {
        if (n < 0)
            throw new IllegalArgumentException("List length = " + n);
        return new CopiesList<>(n, o);
    }

正如我们所见,它返回的是 CopiesList 对象,而不是 ArrayList。 此外,与其他列表一样,它扩展了 AbstractList:

private static class CopiesList<E>
        extends AbstractList<E>
        implements RandomAccess, Serializable
    {
        private static final long serialVersionUID = 2739099268398711800L;

        final int n;
        final E element;

        CopiesList(int n, E e) {
            assert n >= 0;
            this.n = n;
            element = e;
        }
...}

虽然不是 ArrayList,但是感谢您的建议和建议,没有空话和题外话,我将使用您的解决方案。

【问题讨论】:

  • 您发布的第二个链接 (List&lt;Integer&gt; list = new ArrayList&lt;Integer&gt;(Collections.nCopies(60, 0))) 正是您所需要的,它确实创建了一个 ArrayList
  • 在同一个对象上存储 70 次引用有什么意义?
  • 发现了,这是解决 TableView+Pagination 与 Hibernate 和 Spring 集成中的一些 JavaFX 问题的一个大型解决方案(仅以 70 为例)。解释这个问题需要很长时间。

标签: java arraylist collections java-stream


【解决方案1】:

您可以手动构建流:

List<SomeObject> list = Stream.generate(() -> someObject).limit(70).collect(toList());
//or if you want to make sure you get an ArrayList:
List<SomeObject> list = Stream.generate(() -> someObject).limit(70).collect(toCollection(ArrayList::new));

虽然仅仅为此目的创建流可能效率低下,但我可能会接受@Eran 的建议:

List<SomeObject> list = Collections.nCopies(70, someObject);
//or if you want to make sure you get an ArrayList:
List<SomeObject> list = new ArrayList<> (Collections.nCopies(70, someObject));

【讨论】:

  • 感谢您的回答,我已经更新了问题,也许您可​​以在这部分添加一些内容?
  • 你总是可以写new ArrayList&lt;&gt; (Collections.nCopies(70, someObject)),但你为什么想要一个ArrayList?
  • 当我尝试通过方法 addAll() 将另一个列表(另一个 ArrayList)添加到此列表(从 nCopies 创建的列表)时 - 我收到 UnsupportedOperationException,但如果我将列表从 nCopies 添加到另一个- 一切正常,所以我认为你是对的 - 现在不是重点。非常感谢!真的有帮助!
  • 请注意,使用toList()收集器的流解决方案发生返回ArrayList,但不保证它。你必须使用toCollection(ArrayList::new),如果它真的必须是ArrayList。但即使使用流,Collections.nCopies(70, someObject).stream() 也可能是更有效的流源。相当于IntStream.range(0, 70).mapToObj(i -&gt; someObject)...
【解决方案2】:

您基本上可以使用 IntStream.range() 并使用 mapToObj 方法将每个 int 映射到同一个对象并将其收集到一个列表中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-26
    相关资源
    最近更新 更多